This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [CHKP, PATCH] Fix instrumented indirect calls with propagated pointers
- From: Ilya Enkovich <enkovich dot gnu at gmail dot com>
- To: Jan Hubicka <hubicka at ucw dot cz>
- Cc: Jakub Jelinek <jakub at redhat dot com>, gcc-patches <gcc-patches at gcc dot gnu dot org>
- Date: Tue, 19 May 2015 12:39:51 +0300
- Subject: Re: [CHKP, PATCH] Fix instrumented indirect calls with propagated pointers
- Authentication-results: sourceware.org; auth=none
- References: <20150312100931 dot GK27860 at msticlxl57 dot ims dot intel dot com> <20150319082944 dot GC64546 at msticlxl57 dot ims dot intel dot com> <20150324083325 dot GC1746 at tucnak dot redhat dot com> <CAMbmDYbs2GEy3=gQ1+3NDZuqATeiRZbhfucsx3AWP8Zmq2zogA at mail dot gmail dot com> <20150324140619 dot GE1746 at tucnak dot redhat dot com> <20150402162754 dot GE6244 at msticlxl57 dot ims dot intel dot com> <20150410012759 dot GB2320 at atrey dot karlin dot mff dot cuni dot cz> <20150414143506 dot GB50171 at msticlxl57 dot ims dot intel dot com> <CAMbmDYZyB6x29UQER4P0r9DaHS4KVdXRqw3tN=FZ-=2GPk2wzA at mail dot gmail dot com>
Ping
2015-05-05 11:05 GMT+03:00 Ilya Enkovich <enkovich.gnu@gmail.com>:
> Ping
>
> 2015-04-14 17:35 GMT+03:00 Ilya Enkovich <enkovich.gnu@gmail.com>:
>> On 10 Apr 03:27, Jan Hubicka wrote:
>>> >
>>> > + /* We might propagate instrumented function pointer into
>>> > + not instrumented function and vice versa. In such a
>>> > + case we need to either fix function declaration or
>>> > + remove bounds from call statement. */
>>> > + if (flag_check_pointer_bounds && callee)
>>> > + skip_bounds = chkp_redirect_edge (e);
>>>
>>> I think this gets wrong the case where the edge is speculative and the new
>>> direct call needs adjustement. You probably need to do the right think in
>>> the if (e->speculative) branch so direct call is updated by indirect is not
>>> or at least give an explanation why this is not needed :)
>>>
>>> The speculative edge handling works in a way that the runtime conditoinal is
>>> built and then the edge is updated to the direct path, so perhaps
>>> you can just move all this after the ocnditoinal?
>>
>> I think you are right, it should be OK to move it after apeculative call processing.
>>
>>>
>>> > diff --git a/gcc/lto-wrapper.c b/gcc/lto-wrapper.c
>>> > index 404cb68..ffb6ad7 100644
>>> > --- a/gcc/lto-wrapper.c
>>> > +++ b/gcc/lto-wrapper.c
>>> > @@ -273,6 +273,7 @@ merge_and_complain (struct cl_decoded_option **decoded_options,
>>> > case OPT_fwrapv:
>>> > case OPT_fopenmp:
>>> > case OPT_fopenacc:
>>> > + case OPT_fcheck_pointer_bounds:
>>> > /* For selected options we can merge conservatively. */
>>> > for (j = 0; j < *decoded_options_count; ++j)
>>> > if ((*decoded_options)[j].opt_index == foption->opt_index)
>>> > @@ -503,6 +504,7 @@ append_compiler_options (obstack *argv_obstack, struct cl_decoded_option *opts,
>>> > case OPT_Ofast:
>>> > case OPT_Og:
>>> > case OPT_Os:
>>> > + case OPT_fcheck_pointer_bounds:
>>>
>>> Hmm, will this make mixed units contaiing some check bounds and some non-check bounds to work?
>>> Perhaps these should be function specific? Does things like inlining bounds checked function into
>>> non-checked function work?
>>
>> This actually should make it work better because solves a possible problem with uninitialized static bounds data (chkp static constructors are generated only when OPT_fcheck_pointer_bounds is passed).
>>
>> Inlining of instrumentation thunks is not supported (similar to all other thunks). But we may have a not instrumented call in an instrumented function and do inlining for it.
>>
>>>
>>> Otherwise the patch seems resonable.
>>> Honza
>>
>>
>> Here is a fixed version with chkp redirection moved. Bootstrap and testing passed. Is it OK for trunk and later for GCC 5?
>>
>> Thanks,
>> Ilya
>> --
>> gcc/
>>
>> 2015-04-14 Ilya Enkovich <ilya.enkovich@intel.com>
>>
>> PR target/65527
>> * cgraph.c (cgraph_edge::redirect_call_stmt_to_callee): Add
>> redirection for instrumented calls.
>> * lto-wrapper.c (merge_and_complain): Merge -fcheck-pointer-bounds.
>> (append_compiler_options): Append -fcheck-pointer-bounds.
>> * tree-chkp.h (chkp_copy_call_skip_bounds): New.
>> (chkp_redirect_edge): New.
>> * tree-chkp.c (chkp_copy_call_skip_bounds): New.
>> (chkp_redirect_edge): New.
>>
>> gcc/testsuite/
>>
>> 2015-04-14 Ilya Enkovich <ilya.enkovich@intel.com>
>>
>> PR target/65527
>> * gcc.target/i386/mpx/chkp-fix-calls-1.c: New.
>> * gcc.target/i386/mpx/chkp-fix-calls-2.c: New.
>> * gcc.target/i386/mpx/chkp-fix-calls-3.c: New.
>> * gcc.target/i386/mpx/chkp-fix-calls-4.c: New.
>>
>>
>> diff --git a/gcc/cgraph.c b/gcc/cgraph.c
>> index 85531c8..38e71fc 100644
>> --- a/gcc/cgraph.c
>> +++ b/gcc/cgraph.c
>> @@ -1281,6 +1281,7 @@ cgraph_edge::redirect_call_stmt_to_callee (void)
>> tree lhs = gimple_call_lhs (e->call_stmt);
>> gcall *new_stmt;
>> gimple_stmt_iterator gsi;
>> + bool skip_bounds = false;
>> #ifdef ENABLE_CHECKING
>> cgraph_node *node;
>> #endif
>> @@ -1389,8 +1390,16 @@ cgraph_edge::redirect_call_stmt_to_callee (void)
>> }
>> }
>>
>> + /* We might propagate instrumented function pointer into
>> + not instrumented function and vice versa. In such a
>> + case we need to either fix function declaration or
>> + remove bounds from call statement. */
>> + if (flag_check_pointer_bounds && e->callee)
>> + skip_bounds = chkp_redirect_edge (e);
>> +
>> if (e->indirect_unknown_callee
>> - || decl == e->callee->decl)
>> + || (decl == e->callee->decl
>> + && !skip_bounds))
>> return e->call_stmt;
>>
>> #ifdef ENABLE_CHECKING
>> @@ -1415,13 +1424,19 @@ cgraph_edge::redirect_call_stmt_to_callee (void)
>> }
>> }
>>
>> - if (e->callee->clone.combined_args_to_skip)
>> + if (e->callee->clone.combined_args_to_skip
>> + || skip_bounds)
>> {
>> int lp_nr;
>>
>> - new_stmt
>> - = gimple_call_copy_skip_args (e->call_stmt,
>> - e->callee->clone.combined_args_to_skip);
>> + new_stmt = e->call_stmt;
>> + if (e->callee->clone.combined_args_to_skip)
>> + new_stmt
>> + = gimple_call_copy_skip_args (new_stmt,
>> + e->callee->clone.combined_args_to_skip);
>> + if (skip_bounds)
>> + new_stmt = chkp_copy_call_skip_bounds (new_stmt);
>> +
>> gimple_call_set_fndecl (new_stmt, e->callee->decl);
>> gimple_call_set_fntype (new_stmt, gimple_call_fntype (e->call_stmt));
>>
>> diff --git a/gcc/lto-wrapper.c b/gcc/lto-wrapper.c
>> index 404cb68..ffb6ad7 100644
>> --- a/gcc/lto-wrapper.c
>> +++ b/gcc/lto-wrapper.c
>> @@ -273,6 +273,7 @@ merge_and_complain (struct cl_decoded_option **decoded_options,
>> case OPT_fwrapv:
>> case OPT_fopenmp:
>> case OPT_fopenacc:
>> + case OPT_fcheck_pointer_bounds:
>> /* For selected options we can merge conservatively. */
>> for (j = 0; j < *decoded_options_count; ++j)
>> if ((*decoded_options)[j].opt_index == foption->opt_index)
>> @@ -503,6 +504,7 @@ append_compiler_options (obstack *argv_obstack, struct cl_decoded_option *opts,
>> case OPT_Ofast:
>> case OPT_Og:
>> case OPT_Os:
>> + case OPT_fcheck_pointer_bounds:
>> break;
>>
>> default:
>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/chkp-fix-calls-1.c b/gcc/testsuite/gcc.target/i386/mpx/chkp-fix-calls-1.c
>> new file mode 100644
>> index 0000000..cb4d229
>> --- /dev/null
>> +++ b/gcc/testsuite/gcc.target/i386/mpx/chkp-fix-calls-1.c
>> @@ -0,0 +1,16 @@
>> +/* { dg-do compile } */
>> +/* { dg-options "-O2 -fcheck-pointer-bounds -mmpx" } */
>> +
>> +#include "math.h"
>> +
>> +double
>> +test1 (double x, double y, double (*fn)(double, double))
>> +{
>> + return fn (x, y);
>> +}
>> +
>> +double
>> +test2 (double x, double y)
>> +{
>> + return test1 (x, y, copysign);
>> +}
>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/chkp-fix-calls-2.c b/gcc/testsuite/gcc.target/i386/mpx/chkp-fix-calls-2.c
>> new file mode 100644
>> index 0000000..951e7de
>> --- /dev/null
>> +++ b/gcc/testsuite/gcc.target/i386/mpx/chkp-fix-calls-2.c
>> @@ -0,0 +1,16 @@
>> +/* { dg-do compile } */
>> +/* { dg-options "-O3 -fcheck-pointer-bounds -mmpx -fno-inline" } */
>> +
>> +#include "math.h"
>> +
>> +double
>> +test1 (double x, double y, double (*fn)(double, double))
>> +{
>> + return fn (x, y);
>> +}
>> +
>> +double
>> +test2 (double x, double y)
>> +{
>> + return test1 (x, y, copysign);
>> +}
>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/chkp-fix-calls-3.c b/gcc/testsuite/gcc.target/i386/mpx/chkp-fix-calls-3.c
>> new file mode 100755
>> index 0000000..439f631
>> --- /dev/null
>> +++ b/gcc/testsuite/gcc.target/i386/mpx/chkp-fix-calls-3.c
>> @@ -0,0 +1,33 @@
>> +/* { dg-do compile } */
>> +/* { dg-options "-O2 -fexceptions -fcheck-pointer-bounds -mmpx" } */
>> +
>> +extern int f2 (const char*, int, ...);
>> +extern long int f3 (int *);
>> +extern void err (void) __attribute__((__error__("error")));
>> +
>> +extern __inline __attribute__ ((__always_inline__)) int
>> +f1 (int i, ...)
>> +{
>> + if (__builtin_constant_p (i))
>> + {
>> + if (i)
>> + err ();
>> + return f2 ("", i);
>> + }
>> +
>> + return f2 ("", i);
>> +}
>> +
>> +int
>> +test ()
>> +{
>> + int i;
>> +
>> + if (f1 (0))
>> + if (f3 (&i))
>> + i = 0;
>> +
>> + return i;
>> +}
>> +
>> +
>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/chkp-fix-calls-4.c b/gcc/testsuite/gcc.target/i386/mpx/chkp-fix-calls-4.c
>> new file mode 100644
>> index 0000000..1b7d703
>> --- /dev/null
>> +++ b/gcc/testsuite/gcc.target/i386/mpx/chkp-fix-calls-4.c
>> @@ -0,0 +1,17 @@
>> +/* { dg-do compile } */
>> +/* { dg-options "-Os -fcheck-pointer-bounds -mmpx" } */
>> +
>> +typedef void (func) (int *);
>> +
>> +static inline void
>> +bar (func f)
>> +{
>> + int i;
>> + f (&i);
>> +}
>> +
>> +void
>> +foo ()
>> +{
>> + bar (0);
>> +}
>> diff --git a/gcc/tree-chkp.c b/gcc/tree-chkp.c
>> index 8c5a628..c2d9e94 100644
>> --- a/gcc/tree-chkp.c
>> +++ b/gcc/tree-chkp.c
>> @@ -529,6 +529,71 @@ chkp_insert_retbnd_call (tree bndval, tree retval,
>> return bndval;
>> }
>>
>> +/* Build a GIMPLE_CALL identical to CALL but skipping bounds
>> + arguments. */
>> +
>> +gcall *
>> +chkp_copy_call_skip_bounds (gcall *call)
>> +{
>> + bitmap bounds;
>> + unsigned i;
>> +
>> + bitmap_obstack_initialize (NULL);
>> + bounds = BITMAP_ALLOC (NULL);
>> +
>> + for (i = 0; i < gimple_call_num_args (call); i++)
>> + if (POINTER_BOUNDS_P (gimple_call_arg (call, i)))
>> + bitmap_set_bit (bounds, i);
>> +
>> + if (!bitmap_empty_p (bounds))
>> + call = gimple_call_copy_skip_args (call, bounds);
>> + gimple_call_set_with_bounds (call, false);
>> +
>> + BITMAP_FREE (bounds);
>> + bitmap_obstack_release (NULL);
>> +
>> + return call;
>> +}
>> +
>> +/* Redirect edge E to the correct node according to call_stmt.
>> + Return 1 if bounds removal from call_stmt should be done
>> + instead of redirection. */
>> +
>> +bool
>> +chkp_redirect_edge (cgraph_edge *e)
>> +{
>> + bool instrumented = false;
>> + tree decl = e->callee->decl;
>> +
>> + if (e->callee->instrumentation_clone
>> + || chkp_function_instrumented_p (decl))
>> + instrumented = true;
>> +
>> + if (instrumented
>> + && !gimple_call_with_bounds_p (e->call_stmt))
>> + e->redirect_callee (cgraph_node::get_create (e->callee->orig_decl));
>> + else if (!instrumented
>> + && gimple_call_with_bounds_p (e->call_stmt)
>> + && !chkp_gimple_call_builtin_p (e->call_stmt, BUILT_IN_CHKP_BNDCL)
>> + && !chkp_gimple_call_builtin_p (e->call_stmt, BUILT_IN_CHKP_BNDCU)
>> + && !chkp_gimple_call_builtin_p (e->call_stmt, BUILT_IN_CHKP_BNDSTX))
>> + {
>> + if (e->callee->instrumented_version)
>> + e->redirect_callee (e->callee->instrumented_version);
>> + else
>> + {
>> + tree args = TYPE_ARG_TYPES (TREE_TYPE (decl));
>> + /* Avoid bounds removal if all args will be removed. */
>> + if (!args || TREE_VALUE (args) != void_type_node)
>> + return true;
>> + else
>> + gimple_call_set_with_bounds (e->call_stmt, false);
>> + }
>> + }
>> +
>> + return false;
>> +}
>> +
>> /* Mark statement S to not be instrumented. */
>> static void
>> chkp_mark_stmt (gimple s)
>> diff --git a/gcc/tree-chkp.h b/gcc/tree-chkp.h
>> index 1bafe99..b5ab562 100644
>> --- a/gcc/tree-chkp.h
>> +++ b/gcc/tree-chkp.h
>> @@ -56,5 +56,7 @@ extern bool chkp_gimple_call_builtin_p (gimple call,
>> extern void chkp_expand_bounds_reset_for_mem (tree mem, tree ptr);
>> extern tree chkp_insert_retbnd_call (tree bndval, tree retval,
>> gimple_stmt_iterator *gsi);
>> +extern gcall *chkp_copy_call_skip_bounds (gcall *call);
>> +extern bool chkp_redirect_edge (cgraph_edge *e);
>>
>> #endif /* GCC_TREE_CHKP_H */