On 14 Nov 23:40, Jeff Law wrote: > On 11/06/14 05:39, Ilya Enkovich wrote: > >Hi, > > > >This patch adds support of instrumented function calls into strlen pass. > > > >Whole series pass bootstrap and check on linux-x86_64. OK for trunk? > > > >Thanks, > >Ilya > >-- > >gcc/ > > > >2014-11-06 Ilya Enkovich <ilya.enkov...@intel.com> > > > > * tree-ssa-strlen.c: include ipa-chkp.h. > > (get_string_length): Handle calls with bounds. > > (adjust_last_stmt): Likewise. > > (handle_builtin_strchr): Likewise. > > (handle_builtin_strcpy): Likewise. > > (handle_builtin_memcpy): Likewise. > > (handle_builtin_strcat): Likewise. > > > >gcc/testsuite/ > > > >2014-11-06 Ilya Enkovich <ilya.enkov...@intel.com> > > > > * gcc.target/i386/chkp-strlen-1.c: New. > > * gcc.target/i386/chkp-strlen-2.c: New. > > * gcc.target/i386/chkp-strlen-3.c: New. > > * gcc.target/i386/chkp-strlen-4.c: New. > > * gcc.target/i386/chkp-strlen-5.c: New. > > > > > > >diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c > >index c224fd9..10db136 100644 > >--- a/gcc/tree-ssa-strlen.c > >+++ b/gcc/tree-ssa-strlen.c > >@@ -62,6 +62,10 @@ along with GCC; see the file COPYING3. If not see > > #include "gimple-pretty-print.h" > > #include "params.h" > > #include "expr.h" > >+#include "ipa-ref.h" > >+#include "lto-streamer.h" > >+#include "cgraph.h" > >+#include "ipa-chkp.h" > Really, ipa-ref, lto-streamer, cgraph? What are these needed for? > > OK after attempting to trim out unnecessary includes. > > Jeff >
Clones search uses cgraph_node and therefore I need cgraph.h. After r216805 (https://gcc.gnu.org/ml/gcc-cvs/2014-10/msg01068.html) cgraph.h requires some additional includes. r216805 does following change in a lot of files: +#include "hash-map.h" +#include "is-a.h" +#include "plugin-api.h" +#include "ipa-ref.h" #include "cgraph.h" lto-streamer.h just worked for me instead of plugin-api.h. I replaced it with plugin-api.h. Below is a fixed version to be committed. Thanks Ilya -- diff --git a/gcc/testsuite/gcc.target/i386/chkp-strlen-1.c b/gcc/testsuite/gcc.target/i386/chkp-strlen-1.c new file mode 100644 index 0000000..ffb4f16 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/chkp-strlen-1.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target mpx } */ +/* { dg-options "-fcheck-pointer-bounds -mmpx -O2 -fdump-tree-strlen" } */ +/* { dg-final { scan-tree-dump "memcpy.chkp" "strlen" } } */ +/* { dg-final { cleanup-tree-dump "strlen" } } */ + +#include "string.h" + +char *test (char *str1, char *str2) +{ + size_t len = strlen (str2); + strcpy (str1, str2); + return str1 + len; +} diff --git a/gcc/testsuite/gcc.target/i386/chkp-strlen-2.c b/gcc/testsuite/gcc.target/i386/chkp-strlen-2.c new file mode 100644 index 0000000..1ce426d --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/chkp-strlen-2.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target mpx } */ +/* { dg-options "-fcheck-pointer-bounds -mmpx -O2 -fdump-tree-strlen" } */ +/* { dg-final { scan-tree-dump-not "strlen" "strlen" } } */ +/* { dg-final { cleanup-tree-dump "strlen" } } */ + +#include "string.h" + +char *test (char *str1, char *str2) +{ + char *p = stpcpy (str1, str2); + size_t len = strlen (str1); + return p + len; +} diff --git a/gcc/testsuite/gcc.target/i386/chkp-strlen-3.c b/gcc/testsuite/gcc.target/i386/chkp-strlen-3.c new file mode 100644 index 0000000..447b9be --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/chkp-strlen-3.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target mpx } */ +/* { dg-options "-fcheck-pointer-bounds -mmpx -O2 -fdump-tree-strlen" } */ +/* { dg-final { scan-tree-dump-times "strlen" 1 "strlen" } } */ +/* { dg-final { cleanup-tree-dump "strlen" } } */ + +#include "string.h" + +size_t test (char *str1, char *str2) +{ + size_t len = strlen (str2); + memcpy (str1, str2, len + 1); + return len + strlen (str1); +} diff --git a/gcc/testsuite/gcc.target/i386/chkp-strlen-4.c b/gcc/testsuite/gcc.target/i386/chkp-strlen-4.c new file mode 100644 index 0000000..a9ebe2b --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/chkp-strlen-4.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target mpx } */ +/* { dg-options "-fcheck-pointer-bounds -mmpx -O2 -fdump-tree-strlen -D_GNU_SOURCE" } */ +/* { dg-final { scan-tree-dump-times "strlen" 1 "strlen" } } */ +/* { dg-final { cleanup-tree-dump "strlen" } } */ + +#include "string.h" + +char * test (char *str1, char *str2) +{ + size_t len = strlen (str2); + char *p = (char *)mempcpy (str1, str2, len + 1); + return p + len + strlen (str1); +} diff --git a/gcc/testsuite/gcc.target/i386/chkp-strlen-5.c b/gcc/testsuite/gcc.target/i386/chkp-strlen-5.c new file mode 100644 index 0000000..37b664e --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/chkp-strlen-5.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target mpx } */ +/* { dg-options "-fcheck-pointer-bounds -mmpx -O2 -fdump-tree-strlen" } */ +/* { dg-final { scan-tree-dump-times "strlen" 2 "strlen" } } */ +/* { dg-final { scan-tree-dump "memcpy" "strlen" } } */ +/* { dg-final { cleanup-tree-dump "strlen" } } */ + +#include "string.h" + +size_t test (char *str1, char *str2) +{ + size_t len1 = strlen (str1); + size_t len2 = strlen (str2); + strcat (str1, str2); + return len1 + len2 + strlen (str1); +} diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c index 3789e30..c327f89 100644 --- a/gcc/tree-ssa-strlen.c +++ b/gcc/tree-ssa-strlen.c @@ -62,6 +62,10 @@ along with GCC; see the file COPYING3. If not see #include "gimple-pretty-print.h" #include "params.h" #include "expr.h" +#include "plugin-api.h" +#include "ipa-ref.h" +#include "cgraph.h" +#include "ipa-chkp.h" /* A vector indexed by SSA_NAME_VERSION. 0 means unknown, positive value is an index into strinfo vector, negative value stands for @@ -417,6 +421,7 @@ get_string_length (strinfo si) if (si->stmt) { gimple stmt = si->stmt, lenstmt; + bool with_bounds = gimple_call_with_bounds_p (stmt); tree callee, lhs, fn, tem; location_t loc; gimple_stmt_iterator gsi; @@ -436,11 +441,20 @@ get_string_length (strinfo si) { case BUILT_IN_STRCAT: case BUILT_IN_STRCAT_CHK: + case BUILT_IN_STRCAT_CHKP: + case BUILT_IN_STRCAT_CHK_CHKP: gsi = gsi_for_stmt (stmt); fn = builtin_decl_implicit (BUILT_IN_STRLEN); gcc_assert (lhs == NULL_TREE); tem = unshare_expr (gimple_call_arg (stmt, 0)); - lenstmt = gimple_build_call (fn, 1, tem); + if (with_bounds) + { + lenstmt = gimple_build_call (chkp_maybe_create_clone (fn)->decl, + 2, tem, gimple_call_arg (stmt, 1)); + gimple_call_set_with_bounds (lenstmt, true); + } + else + lenstmt = gimple_build_call (fn, 1, tem); lhs = make_ssa_name (TREE_TYPE (TREE_TYPE (fn)), lenstmt); gimple_call_set_lhs (lenstmt, lhs); gimple_set_vuse (lenstmt, gimple_vuse (stmt)); @@ -463,10 +477,14 @@ get_string_length (strinfo si) /* FALLTHRU */ case BUILT_IN_STRCPY: case BUILT_IN_STRCPY_CHK: - if (gimple_call_num_args (stmt) == 2) + case BUILT_IN_STRCPY_CHKP: + case BUILT_IN_STRCPY_CHK_CHKP: + if (gimple_call_num_args (stmt) == (with_bounds ? 4 : 2)) fn = builtin_decl_implicit (BUILT_IN_STPCPY); else fn = builtin_decl_explicit (BUILT_IN_STPCPY_CHK); + if (with_bounds) + fn = chkp_maybe_create_clone (fn)->decl; gcc_assert (lhs == NULL_TREE); if (dump_file && (dump_flags & TDF_DETAILS) != 0) { @@ -485,6 +503,8 @@ get_string_length (strinfo si) /* FALLTHRU */ case BUILT_IN_STPCPY: case BUILT_IN_STPCPY_CHK: + case BUILT_IN_STPCPY_CHKP: + case BUILT_IN_STPCPY_CHK_CHKP: gcc_assert (lhs != NULL_TREE); loc = gimple_location (stmt); si->endptr = lhs; @@ -775,6 +795,7 @@ adjust_last_stmt (strinfo si, gimple stmt, bool is_strcat) tree vuse, callee, len; struct laststmt_struct last = laststmt; strinfo lastsi, firstsi; + unsigned len_arg_no = 2; laststmt.stmt = NULL; laststmt.len = NULL_TREE; @@ -846,11 +867,15 @@ adjust_last_stmt (strinfo si, gimple stmt, bool is_strcat) case BUILT_IN_MEMCPY: case BUILT_IN_MEMCPY_CHK: break; + case BUILT_IN_MEMCPY_CHKP: + case BUILT_IN_MEMCPY_CHK_CHKP: + len_arg_no = 4; + break; default: return; } - len = gimple_call_arg (last.stmt, 2); + len = gimple_call_arg (last.stmt, len_arg_no); if (tree_fits_uhwi_p (len)) { if (!tree_fits_uhwi_p (last.len) @@ -874,7 +899,7 @@ adjust_last_stmt (strinfo si, gimple stmt, bool is_strcat) else return; - gimple_call_set_arg (last.stmt, 2, last.len); + gimple_call_set_arg (last.stmt, len_arg_no, last.len); update_stmt (last.stmt); } @@ -965,11 +990,12 @@ handle_builtin_strchr (gimple_stmt_iterator *gsi) tree src; gimple stmt = gsi_stmt (*gsi); tree lhs = gimple_call_lhs (stmt); + bool with_bounds = gimple_call_with_bounds_p (stmt); if (lhs == NULL_TREE) return; - if (!integer_zerop (gimple_call_arg (stmt, 1))) + if (!integer_zerop (gimple_call_arg (stmt, with_bounds ? 2 : 1))) return; src = gimple_call_arg (stmt, 0); @@ -1076,8 +1102,9 @@ handle_builtin_strcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi) gimple stmt = gsi_stmt (*gsi); strinfo si, dsi, olddsi, zsi; location_t loc; + bool with_bounds = gimple_call_with_bounds_p (stmt); - src = gimple_call_arg (stmt, 1); + src = gimple_call_arg (stmt, with_bounds ? 2 : 1); dst = gimple_call_arg (stmt, 0); lhs = gimple_call_lhs (stmt); idx = get_stridx (src); @@ -1108,11 +1135,15 @@ handle_builtin_strcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi) { case BUILT_IN_STRCPY: case BUILT_IN_STRCPY_CHK: + case BUILT_IN_STRCPY_CHKP: + case BUILT_IN_STRCPY_CHK_CHKP: if (lhs != NULL_TREE || !builtin_decl_implicit_p (BUILT_IN_STPCPY)) return; break; case BUILT_IN_STPCPY: case BUILT_IN_STPCPY_CHK: + case BUILT_IN_STPCPY_CHKP: + case BUILT_IN_STPCPY_CHK_CHKP: if (lhs == NULL_TREE) return; else @@ -1211,16 +1242,19 @@ handle_builtin_strcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi) switch (bcode) { case BUILT_IN_STRCPY: + case BUILT_IN_STRCPY_CHKP: fn = builtin_decl_implicit (BUILT_IN_MEMCPY); if (lhs) ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)] = didx; break; case BUILT_IN_STRCPY_CHK: + case BUILT_IN_STRCPY_CHK_CHKP: fn = builtin_decl_explicit (BUILT_IN_MEMCPY_CHK); if (lhs) ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)] = didx; break; case BUILT_IN_STPCPY: + case BUILT_IN_STPCPY_CHKP: /* This would need adjustment of the lhs (subtract one), or detection that the trailing '\0' doesn't need to be written, if it will be immediately overwritten. @@ -1232,6 +1266,7 @@ handle_builtin_strcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi) } break; case BUILT_IN_STPCPY_CHK: + case BUILT_IN_STPCPY_CHK_CHKP: /* This would need adjustment of the lhs (subtract one), or detection that the trailing '\0' doesn't need to be written, if it will be immediately overwritten. @@ -1263,14 +1298,33 @@ handle_builtin_strcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi) fprintf (dump_file, "Optimizing: "); print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM); } - if (gimple_call_num_args (stmt) == 2) - success = update_gimple_call (gsi, fn, 3, dst, src, len); + if (with_bounds) + { + fn = chkp_maybe_create_clone (fn)->decl; + if (gimple_call_num_args (stmt) == 4) + success = update_gimple_call (gsi, fn, 5, dst, + gimple_call_arg (stmt, 1), + src, + gimple_call_arg (stmt, 3), + len); + else + success = update_gimple_call (gsi, fn, 6, dst, + gimple_call_arg (stmt, 1), + src, + gimple_call_arg (stmt, 3), + len, + gimple_call_arg (stmt, 4)); + } else - success = update_gimple_call (gsi, fn, 4, dst, src, len, - gimple_call_arg (stmt, 2)); + if (gimple_call_num_args (stmt) == 2) + success = update_gimple_call (gsi, fn, 3, dst, src, len); + else + success = update_gimple_call (gsi, fn, 4, dst, src, len, + gimple_call_arg (stmt, 2)); if (success) { stmt = gsi_stmt (*gsi); + gimple_call_set_with_bounds (stmt, with_bounds); update_stmt (stmt); if (dump_file && (dump_flags & TDF_DETAILS) != 0) { @@ -1298,9 +1352,10 @@ handle_builtin_memcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi) tree src, dst, len, lhs, oldlen, newlen; gimple stmt = gsi_stmt (*gsi); strinfo si, dsi, olddsi; + bool with_bounds = gimple_call_with_bounds_p (stmt); - len = gimple_call_arg (stmt, 2); - src = gimple_call_arg (stmt, 1); + len = gimple_call_arg (stmt, with_bounds ? 4 : 2); + src = gimple_call_arg (stmt, with_bounds ? 2 : 1); dst = gimple_call_arg (stmt, 0); idx = get_stridx (src); if (idx == 0) @@ -1407,6 +1462,8 @@ handle_builtin_memcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi) { case BUILT_IN_MEMCPY: case BUILT_IN_MEMCPY_CHK: + case BUILT_IN_MEMCPY_CHKP: + case BUILT_IN_MEMCPY_CHK_CHKP: /* Allow adjust_last_stmt to decrease this memcpy's size. */ laststmt.stmt = stmt; laststmt.len = dsi->length; @@ -1416,6 +1473,8 @@ handle_builtin_memcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi) break; case BUILT_IN_MEMPCPY: case BUILT_IN_MEMPCPY_CHK: + case BUILT_IN_MEMPCPY_CHKP: + case BUILT_IN_MEMPCPY_CHK_CHKP: break; default: gcc_unreachable (); @@ -1437,8 +1496,9 @@ handle_builtin_strcat (enum built_in_function bcode, gimple_stmt_iterator *gsi) gimple stmt = gsi_stmt (*gsi); strinfo si, dsi; location_t loc; + bool with_bounds = gimple_call_with_bounds_p (stmt); - src = gimple_call_arg (stmt, 1); + src = gimple_call_arg (stmt, with_bounds ? 2 : 1); dst = gimple_call_arg (stmt, 0); lhs = gimple_call_lhs (stmt); @@ -1534,17 +1594,19 @@ handle_builtin_strcat (enum built_in_function bcode, gimple_stmt_iterator *gsi) switch (bcode) { case BUILT_IN_STRCAT: + case BUILT_IN_STRCAT_CHKP: if (srclen != NULL_TREE) fn = builtin_decl_implicit (BUILT_IN_MEMCPY); else fn = builtin_decl_implicit (BUILT_IN_STRCPY); break; case BUILT_IN_STRCAT_CHK: + case BUILT_IN_STRCAT_CHK_CHKP: if (srclen != NULL_TREE) fn = builtin_decl_explicit (BUILT_IN_MEMCPY_CHK); else fn = builtin_decl_explicit (BUILT_IN_STRCPY_CHK); - objsz = gimple_call_arg (stmt, 2); + objsz = gimple_call_arg (stmt, with_bounds ? 4 : 2); break; default: gcc_unreachable (); @@ -1579,15 +1641,35 @@ handle_builtin_strcat (enum built_in_function bcode, gimple_stmt_iterator *gsi) fprintf (dump_file, "Optimizing: "); print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM); } - if (srclen != NULL_TREE) - success = update_gimple_call (gsi, fn, 3 + (objsz != NULL_TREE), - dst, src, len, objsz); + if (with_bounds) + { + fn = chkp_maybe_create_clone (fn)->decl; + if (srclen != NULL_TREE) + success = update_gimple_call (gsi, fn, 5 + (objsz != NULL_TREE), + dst, + gimple_call_arg (stmt, 1), + src, + gimple_call_arg (stmt, 3), + len, objsz); + else + success = update_gimple_call (gsi, fn, 4 + (objsz != NULL_TREE), + dst, + gimple_call_arg (stmt, 1), + src, + gimple_call_arg (stmt, 3), + objsz); + } else - success = update_gimple_call (gsi, fn, 2 + (objsz != NULL_TREE), - dst, src, objsz); + if (srclen != NULL_TREE) + success = update_gimple_call (gsi, fn, 3 + (objsz != NULL_TREE), + dst, src, len, objsz); + else + success = update_gimple_call (gsi, fn, 2 + (objsz != NULL_TREE), + dst, src, objsz); if (success) { stmt = gsi_stmt (*gsi); + gimple_call_set_with_bounds (stmt, with_bounds); update_stmt (stmt); if (dump_file && (dump_flags & TDF_DETAILS) != 0) { @@ -1901,25 +1983,37 @@ strlen_optimize_stmt (gimple_stmt_iterator *gsi) switch (DECL_FUNCTION_CODE (callee)) { case BUILT_IN_STRLEN: + case BUILT_IN_STRLEN_CHKP: handle_builtin_strlen (gsi); break; case BUILT_IN_STRCHR: + case BUILT_IN_STRCHR_CHKP: handle_builtin_strchr (gsi); break; case BUILT_IN_STRCPY: case BUILT_IN_STRCPY_CHK: case BUILT_IN_STPCPY: case BUILT_IN_STPCPY_CHK: + case BUILT_IN_STRCPY_CHKP: + case BUILT_IN_STRCPY_CHK_CHKP: + case BUILT_IN_STPCPY_CHKP: + case BUILT_IN_STPCPY_CHK_CHKP: handle_builtin_strcpy (DECL_FUNCTION_CODE (callee), gsi); break; case BUILT_IN_MEMCPY: case BUILT_IN_MEMCPY_CHK: case BUILT_IN_MEMPCPY: case BUILT_IN_MEMPCPY_CHK: + case BUILT_IN_MEMCPY_CHKP: + case BUILT_IN_MEMCPY_CHK_CHKP: + case BUILT_IN_MEMPCPY_CHKP: + case BUILT_IN_MEMPCPY_CHK_CHKP: handle_builtin_memcpy (DECL_FUNCTION_CODE (callee), gsi); break; case BUILT_IN_STRCAT: case BUILT_IN_STRCAT_CHK: + case BUILT_IN_STRCAT_CHKP: + case BUILT_IN_STRCAT_CHK_CHKP: handle_builtin_strcat (DECL_FUNCTION_CODE (callee), gsi); break; case BUILT_IN_MALLOC: