diff options
author | Frank Ch. Eigler <fche@redhat.com> | 2004-10-02 23:12:49 +0000 |
---|---|---|
committer | Frank Ch. Eigler <fche@gcc.gnu.org> | 2004-10-02 23:12:49 +0000 |
commit | fefbfa216672c77d2f0c4fb26eb36a654c1a88bb (patch) | |
tree | 34af220a8005039a10395e1129f99324b64ce2ae | |
parent | 7848dfcac199f677935254d6631ca03b02b677ea (diff) | |
download | gcc-fefbfa216672c77d2f0c4fb26eb36a654c1a88bb.zip gcc-fefbfa216672c77d2f0c4fb26eb36a654c1a88bb.tar.gz gcc-fefbfa216672c77d2f0c4fb26eb36a654c1a88bb.tar.bz2 |
tree-mudflap.c (mf_build_check_statement_for): Reorganize to take check-base and -limit arguments.
2004-10-02 Frank Ch. Eigler <fche@redhat.com>
* tree-mudflap.c (mf_build_check_statement_for): Reorganize to
take check-base and -limit arguments.
(mf_xform_derefs_1): Reorganize slightly to pass proper base/limit
check ranges for ARRAY_REF and COMPONENT_REF.
(execute_mudflap_fnction_ops, ..._decls): Limit unnecessary
instrumentation.
2004-10-02 Frank Ch. Eigler <fche@redhat.com>
* testsuite/libmudflap.c/pass50-frag.c, fail33-frag.c, fail34-frag.c:
New tests for proper base/limit checking for aggregates.
From-SVN: r88432
-rw-r--r-- | gcc/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/tree-mudflap.c | 71 | ||||
-rw-r--r-- | libmudflap/ChangeLog | 5 | ||||
-rw-r--r-- | libmudflap/testsuite/libmudflap.c/fail33-frag.c | 25 | ||||
-rw-r--r-- | libmudflap/testsuite/libmudflap.c/fail34-frag.c | 22 | ||||
-rw-r--r-- | libmudflap/testsuite/libmudflap.c/pass50-frag.c | 29 |
6 files changed, 144 insertions, 17 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4f13472..dcdaf703 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2004-10-02 Frank Ch. Eigler <fche@redhat.com> + + * tree-mudflap.c (mf_build_check_statement_for): Reorganize to + take check-base and -limit arguments. + (mf_xform_derefs_1): Reorganize slightly to pass proper base/limit + check ranges for ARRAY_REF and COMPONENT_REF. + (execute_mudflap_fnction_ops, ..._decls): Limit unnecessary + instrumentation. + 2004-10-02 Joseph S. Myers <jsm@polyomino.org.uk> * c-objc-common.c (c_tree_printer): Correct description of %E. diff --git a/gcc/tree-mudflap.c b/gcc/tree-mudflap.c index a61a7ad..bc42de7 100644 --- a/gcc/tree-mudflap.c +++ b/gcc/tree-mudflap.c @@ -407,7 +407,10 @@ mudflap_init (void) static void execute_mudflap_function_ops (void) { - if (mf_marked_p (current_function_decl)) + /* Don't instrument functions such as the synthetic constructor + built during mudflap_finish_file. */ + if (mf_marked_p (current_function_decl) || + DECL_ARTIFICIAL (current_function_decl)) return; push_gimplify_context (); @@ -481,7 +484,7 @@ mf_decl_clear_locals (void) } static void -mf_build_check_statement_for (tree addr, tree size, +mf_build_check_statement_for (tree base, tree addr, tree limit, block_stmt_iterator *instr_bsi, location_t *locus, tree dirflag) { @@ -494,6 +497,7 @@ mf_build_check_statement_for (tree addr, tree size, tree mf_value; tree mf_base; tree mf_elem; + tree mf_limit; /* We first need to split the current basic block, and start altering the CFG. This allows us to insert the statements we're about to @@ -557,6 +561,7 @@ mf_build_check_statement_for (tree addr, tree size, mf_value = create_tmp_var (ptrtype, "__mf_value"); mf_elem = create_tmp_var (mf_cache_structptr_type, "__mf_elem"); mf_base = create_tmp_var (mf_uintptr_type, "__mf_base"); + mf_limit = create_tmp_var (mf_uintptr_type, "__mf_limit"); /* Build: __mf_value = <address expression>. */ t = build (MODIFY_EXPR, void_type_node, mf_value, unshare_expr (addr)); @@ -565,9 +570,16 @@ mf_build_check_statement_for (tree addr, tree size, head = tsi_start (t); tsi = tsi_last (t); - /* Build: __mf_base = (uintptr_t)__mf_value. */ + /* Build: __mf_base = (uintptr_t) <base address expression>. */ t = build (MODIFY_EXPR, void_type_node, mf_base, - build1 (NOP_EXPR, mf_uintptr_type, mf_value)); + convert (mf_uintptr_type, unshare_expr (base))); + SET_EXPR_LOCUS (t, locus); + gimplify_to_stmt_list (&t); + tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING); + + /* Build: __mf_limit = (uintptr_t) <limit address expression>. */ + t = build (MODIFY_EXPR, void_type_node, mf_limit, + convert (mf_uintptr_type, unshare_expr (limit))); SET_EXPR_LOCUS (t, locus); gimplify_to_stmt_list (&t); tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING); @@ -590,7 +602,7 @@ mf_build_check_statement_for (tree addr, tree size, /* Quick validity check. if (__mf_elem->low > __mf_base - || (__mf_elem_high < __mf_base + sizeof(T) - 1)) + || (__mf_elem_high < __mf_limit)) { __mf_check (); ... and only if single-threaded: @@ -607,22 +619,19 @@ mf_build_check_statement_for (tree addr, tree size, TYPE_FIELDS (mf_cache_struct_type), NULL_TREE); t = build (GT_EXPR, boolean_type_node, t, mf_base); - /* Construct '__mf_elem->high < __mf_base + sizeof(T) - 1'. + /* Construct '__mf_elem->high < __mf_limit'. First build: 1) u <-- '__mf_elem->high' - 2) v <-- '__mf_base + sizeof (T) - 1'. + 2) v <-- '__mf_limit'. Then build 'u <-- (u < v). */ - u = build (COMPONENT_REF, mf_uintptr_type, build1 (INDIRECT_REF, mf_cache_struct_type, mf_elem), TREE_CHAIN (TYPE_FIELDS (mf_cache_struct_type)), NULL_TREE); - v = convert (mf_uintptr_type, - size_binop (MINUS_EXPR, size, size_one_node)); - v = fold (build (PLUS_EXPR, mf_uintptr_type, mf_base, v)); + v = mf_limit; u = build (LT_EXPR, boolean_type_node, u, v); @@ -647,7 +656,7 @@ mf_build_check_statement_for (tree addr, tree size, the conditional jump, if (__mf_elem->low > __mf_base - || (__mf_elem_high < __mf_base + sizeof(T) - 1)) + || (__mf_elem_high < __mf_limit)) The lowered GIMPLE tree representing this code is in the statement list starting at 'head'. @@ -670,8 +679,14 @@ mf_build_check_statement_for (tree addr, tree size, : *locus), NULL_TREE); u = tree_cons (NULL_TREE, dirflag, u); - u = tree_cons (NULL_TREE, size, u); - u = tree_cons (NULL_TREE, mf_value, u); + /* NB: we pass the overall [base..limit] range to mf_check, + not the [mf_value..mf_value+size-1] range. */ + u = tree_cons (NULL_TREE, + fold (build (PLUS_EXPR, integer_type_node, + fold (build (MINUS_EXPR, mf_uintptr_type, mf_limit, mf_base)), + integer_one_node)), + u); + u = tree_cons (NULL_TREE, mf_base, u); t = build_function_call_expr (mf_check_fndecl, u); gimplify_to_stmt_list (&t); head = tsi_start (t); @@ -701,7 +716,7 @@ static void mf_xform_derefs_1 (block_stmt_iterator *iter, tree *tp, location_t *locus, tree dirflag) { - tree type, ptr_type, addr, size, t; + tree type, ptr_type, addr, base, size, limit, t; /* Don't instrument read operations. */ if (dirflag == integer_zero_node && flag_mudflap_ignore_reads) @@ -756,12 +771,20 @@ mf_xform_derefs_1 (block_stmt_iterator *iter, tree *tp, /* If we got here, we couldn't statically the check. */ ptr_type = build_pointer_type (type); addr = build1 (ADDR_EXPR, ptr_type, t); + base = build1 (ADDR_EXPR, ptr_type, op0); + limit = fold (build (MINUS_EXPR, mf_uintptr_type, + fold (build2 (PLUS_EXPR, mf_uintptr_type, addr, size)), + integer_one_node)); } break; case INDIRECT_REF: addr = TREE_OPERAND (t, 0); ptr_type = TREE_TYPE (addr); + base = addr; + limit = fold (build (MINUS_EXPR, ptr_type_node, + fold (build (PLUS_EXPR, ptr_type_node, base, size)), + integer_one_node)); break; case ARRAY_RANGE_REF: @@ -798,6 +821,12 @@ mf_xform_derefs_1 (block_stmt_iterator *iter, tree *tp, ptr_type = build_pointer_type (type); addr = build1 (ADDR_EXPR, ptr_type, t); } + + /* XXXXXX */ + base = addr; + limit = fold (build (MINUS_EXPR, ptr_type_node, + fold (build (PLUS_EXPR, ptr_type_node, base, size)), + integer_one_node)); } break; @@ -823,6 +852,11 @@ mf_xform_derefs_1 (block_stmt_iterator *iter, tree *tp, addr = TREE_OPERAND (TREE_OPERAND (t, 0), 0); addr = convert (ptr_type_node, addr); addr = fold (build (PLUS_EXPR, ptr_type_node, addr, ofs)); + + base = addr; + limit = fold (build (MINUS_EXPR, ptr_type_node, + fold (build (PLUS_EXPR, ptr_type_node, base, size)), + integer_one_node)); } break; @@ -830,7 +864,7 @@ mf_xform_derefs_1 (block_stmt_iterator *iter, tree *tp, return; } - mf_build_check_statement_for (addr, size, iter, locus, dirflag); + mf_build_check_statement_for (base, addr, limit, iter, locus, dirflag); } static void @@ -891,7 +925,10 @@ mf_xform_derefs (void) static void execute_mudflap_function_decls (void) { - if (mf_marked_p (current_function_decl)) + /* Don't instrument functions such as the synthetic constructor + built during mudflap_finish_file. */ + if (mf_marked_p (current_function_decl) || + DECL_ARTIFICIAL (current_function_decl)) return; push_gimplify_context (); diff --git a/libmudflap/ChangeLog b/libmudflap/ChangeLog index 984e22b..97ab17c 100644 --- a/libmudflap/ChangeLog +++ b/libmudflap/ChangeLog @@ -1,3 +1,8 @@ +2004-10-02 Frank Ch. Eigler <fche@redhat.com> + + * testsuite/libmudflap.c/pass50-frag.c, fail33-frag.c, fail34-frag.c: + New tests for proper base/limit checking for aggregates. + 2004-09-15 Joseph S. Myers <jsm@polyomino.org.uk> * testsuite/libmudflap.c/pass35-frag.c: Update expected message. diff --git a/libmudflap/testsuite/libmudflap.c/fail33-frag.c b/libmudflap/testsuite/libmudflap.c/fail33-frag.c new file mode 100644 index 0000000..5f33be7 --- /dev/null +++ b/libmudflap/testsuite/libmudflap.c/fail33-frag.c @@ -0,0 +1,25 @@ +#include <stdlib.h> + +#define SIZE 16 + +char b[SIZE]; +char a[SIZE]; + +int main () +{ + int i, j=0; + int a_before_b = (& a[0] < & b[0]); + /* Rather than iterating linearly, which would allow loop unrolling + and mapping to pointer manipulation, we traverse the "joined" + arrays in some random order. */ + for (i=0; i<SIZE*2; i++) + { + k=rand()%(SIZE*2)) + j += (a_before_b ? a[k] : b[k]); + } + return j; +} +/* { dg-output "mudflap violation 1.*" } */ +/* { dg-output "Nearby object.*" } */ +/* { dg-output "mudflap object.*\[ab\]" } */ +/* { dg-do run { xfail *-*-* } } */ diff --git a/libmudflap/testsuite/libmudflap.c/fail34-frag.c b/libmudflap/testsuite/libmudflap.c/fail34-frag.c new file mode 100644 index 0000000..f6572b0 --- /dev/null +++ b/libmudflap/testsuite/libmudflap.c/fail34-frag.c @@ -0,0 +1,22 @@ +#include <stdlib.h> + +struct s +{ + int a1[4]; +}; + +struct s a, b; +int idx = 7; /* should pass to the next object */ + +int +main () +{ + int i, j=0; + int a_before_b = (& a < & b); + j = (a_before_b ? a.a1[idx] : b.a1[idx]); + return j; +} +/* { dg-output "mudflap violation 1.*" } */ +/* { dg-output "Nearby object.*" } */ +/* { dg-output "mudflap object.*\[ab\]" } */ +/* { dg-do run { xfail *-*-* } } */ diff --git a/libmudflap/testsuite/libmudflap.c/pass50-frag.c b/libmudflap/testsuite/libmudflap.c/pass50-frag.c new file mode 100644 index 0000000..ac9ee09 --- /dev/null +++ b/libmudflap/testsuite/libmudflap.c/pass50-frag.c @@ -0,0 +1,29 @@ +#include <stdlib.h> + +struct a +{ + int a1[5]; + union + { + int b1[5]; + struct + { + int c1; + int c2; + } b2[4]; + } a2[8]; +}; + +int i1 = 5; +int i2 = 2; +int i3 = 6; +int i4 = 0; + +int +main () +{ + volatile struct a *k = calloc (1, sizeof (struct a)); + k->a2[i1].b1[i2] = k->a2[i3].b2[i4].c2; + free ((void *) k); + return 0; +} |