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
This commit is contained in:
parent
7848dfcac1
commit
fefbfa2166
6 changed files with 144 additions and 17 deletions
|
@ -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.
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -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.
|
||||
|
|
25
libmudflap/testsuite/libmudflap.c/fail33-frag.c
Normal file
25
libmudflap/testsuite/libmudflap.c/fail33-frag.c
Normal file
|
@ -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 *-*-* } } */
|
22
libmudflap/testsuite/libmudflap.c/fail34-frag.c
Normal file
22
libmudflap/testsuite/libmudflap.c/fail34-frag.c
Normal file
|
@ -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 *-*-* } } */
|
29
libmudflap/testsuite/libmudflap.c/pass50-frag.c
Normal file
29
libmudflap/testsuite/libmudflap.c/pass50-frag.c
Normal file
|
@ -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;
|
||||
}
|
Loading…
Add table
Reference in a new issue