diff options
author | Bernd Edlinger <bernd.edlinger@hotmail.de> | 2015-01-02 22:16:59 +0000 |
---|---|---|
committer | Bernd Edlinger <edlinger@gcc.gnu.org> | 2015-01-02 22:16:59 +0000 |
commit | fe86867f07504f643ab9bf1147bac785222cadb0 (patch) | |
tree | 2e150e026804c390ac9333406e3d7552c6a62711 /gcc | |
parent | e4dd5b691d56f11c225e1e1847be3800854634b6 (diff) | |
download | gcc-fe86867f07504f643ab9bf1147bac785222cadb0.zip gcc-fe86867f07504f643ab9bf1147bac785222cadb0.tar.gz gcc-fe86867f07504f643ab9bf1147bac785222cadb0.tar.bz2 |
Instrument bit field and unaligned accesses for TSAN.
gcc/ChangeLog:
2015-01-02 Bernd Edlinger <bernd.edlinger@hotmail.de>
Instrument bit field and unaligned accesses for TSAN.
* sanitizer.def (BUILT_IN_TSAN_READ_RANGE): New built-in function.
(BUILT_IN_TSAN_WRITE_RANGE): New built-in function.
* tsan.c (instrument_expr): Handle COMPONENT_REF and BIT_FIELD_REF.
Use BUILT_IN_TSAN_READ_RANGE and BUILT_IN_TSAN_WRITE_RANGE for
unaligned memory regions.
testsuite/ChangeLog:
2015-01-02 Bernd Edlinger <bernd.edlinger@hotmail.de>
* c-c++-common/tsan/bitfield_race.c: New testcase.
* g++.dg/tsan/aligned_vs_unaligned_race.C: Fixed.
From-SVN: r219150
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/sanitizer.def | 4 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/c-c++-common/tsan/bitfield_race.c | 26 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/tsan/aligned_vs_unaligned_race.C | 8 | ||||
-rw-r--r-- | gcc/tsan.c | 84 |
6 files changed, 122 insertions, 14 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9e62108..3957600 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2015-01-02 Bernd Edlinger <bernd.edlinger@hotmail.de> + + Instrument bit field and unaligned accesses for TSAN. + * sanitizer.def (BUILT_IN_TSAN_READ_RANGE): New built-in function. + (BUILT_IN_TSAN_WRITE_RANGE): New built-in function. + * tsan.c (instrument_expr): Handle COMPONENT_REF and BIT_FIELD_REF. + Use BUILT_IN_TSAN_READ_RANGE and BUILT_IN_TSAN_WRITE_RANGE for + unaligned memory regions. + 2015-01-01 Anthony Green <green@moxielogic.com> * config/moxie/predicates.md (moxie_general_movsrc_operand): diff --git a/gcc/sanitizer.def b/gcc/sanitizer.def index 3fc8c83..723348e 100644 --- a/gcc/sanitizer.def +++ b/gcc/sanitizer.def @@ -188,6 +188,10 @@ DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_WRITE8, "__tsan_write8", BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST) DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_WRITE16, "__tsan_write16", BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST) +DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_READ_RANGE, "__tsan_read_range", + BT_FN_VOID_PTR_PTRMODE, ATTR_NOTHROW_LEAF_LIST) +DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_WRITE_RANGE, "__tsan_write_range", + BT_FN_VOID_PTR_PTRMODE, ATTR_NOTHROW_LEAF_LIST) DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_ATOMIC8_LOAD, "__tsan_atomic8_load", diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a47a1a1..cb1ba68 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2015-01-02 Bernd Edlinger <bernd.edlinger@hotmail.de> + + * c-c++-common/tsan/bitfield_race.c: New testcase. + * g++.dg/tsan/aligned_vs_unaligned_race.C: Fixed. + 2015-01-02 Tobias Burnus <burnus@net-b.de> * gfortran.dg/coarray/collectives_4.f90: New. diff --git a/gcc/testsuite/c-c++-common/tsan/bitfield_race.c b/gcc/testsuite/c-c++-common/tsan/bitfield_race.c new file mode 100644 index 0000000..e8de097 --- /dev/null +++ b/gcc/testsuite/c-c++-common/tsan/bitfield_race.c @@ -0,0 +1,26 @@ +/* { dg-shouldfail "tsan" } */ + +#include <pthread.h> +#include <unistd.h> + +struct bitfield +{ + int a:10; + int b:10; +} Global; + +void *Thread1(void *x) { + sleep(1); + Global.a = 42; + return x; +} + +int main() { + pthread_t t; + pthread_create(&t, 0, Thread1, 0); + Global.b = 43; + pthread_join(t, 0); + return Global.a; +} + +/* { dg-output "WARNING: ThreadSanitizer: data race.*(\n|\r\n|\r)" } */ diff --git a/gcc/testsuite/g++.dg/tsan/aligned_vs_unaligned_race.C b/gcc/testsuite/g++.dg/tsan/aligned_vs_unaligned_race.C index 390be86..e547e0c 100644 --- a/gcc/testsuite/g++.dg/tsan/aligned_vs_unaligned_race.C +++ b/gcc/testsuite/g++.dg/tsan/aligned_vs_unaligned_race.C @@ -1,3 +1,4 @@ +/* { dg-shouldfail "tsan" } */ #include <pthread.h> #include <stdio.h> #include <stdint.h> @@ -11,8 +12,9 @@ void *Thread1(void *x) { void *Thread2(void *x) { char *p1 = reinterpret_cast<char *>(&Global[0]); - uint64_t *p4 = reinterpret_cast<uint64_t *>(p1 + 1); - (*p4)++; + struct __attribute__((packed, aligned(1))) u_uint64_t { uint64_t val; }; + u_uint64_t *p4 = reinterpret_cast<u_uint64_t *>(p1 + 1); + (*p4).val++; return NULL; } @@ -23,7 +25,7 @@ int main() { pthread_join(t[0], NULL); pthread_join(t[1], NULL); printf("Pass\n"); - /* { dg-prune-output "ThreadSanitizer: data race.*(\n|\r\n|\r)" } */ + /* { dg-output "WARNING: ThreadSanitizer: data race.*(\n|\r\n|\r)" } */ /* { dg-output "Pass.*" } */ return 0; } @@ -62,6 +62,7 @@ along with GCC; see the file COPYING3. If not see #include "tree-ssa-propagate.h" #include "tsan.h" #include "asan.h" +#include "builtins.h" /* Number of instrumented memory accesses in the current function. */ @@ -121,13 +122,12 @@ instrument_expr (gimple_stmt_iterator gsi, tree expr, bool is_write) gimple stmt, g; gimple_seq seq; location_t loc; + unsigned int align; size = int_size_in_bytes (TREE_TYPE (expr)); - if (size == -1) + if (size <= 0) return false; - /* For now just avoid instrumenting bit field acceses. - TODO: handle bit-fields as if touching the whole field. */ HOST_WIDE_INT bitsize, bitpos; tree offset; machine_mode mode; @@ -155,17 +155,71 @@ instrument_expr (gimple_stmt_iterator gsi, tree expr, bool is_write) && DECL_HARD_REGISTER (base))) return false; - if (size == 0 - || bitpos % (size * BITS_PER_UNIT) - || bitsize != size * BITS_PER_UNIT) - return false; - stmt = gsi_stmt (gsi); loc = gimple_location (stmt); rhs = is_vptr_store (stmt, expr, is_write); - gcc_checking_assert (rhs != NULL || is_gimple_addressable (expr)); - expr_ptr = build_fold_addr_expr (unshare_expr (expr)); seq = NULL; + + if ((TREE_CODE (expr) == COMPONENT_REF + && DECL_BIT_FIELD_TYPE (TREE_OPERAND (expr, 1))) + || TREE_CODE (expr) == BIT_FIELD_REF) + { + base = TREE_OPERAND (expr, 0); + if (TREE_CODE (expr) == COMPONENT_REF) + { + expr = TREE_OPERAND (expr, 1); + if (is_write && DECL_BIT_FIELD_REPRESENTATIVE (expr)) + expr = DECL_BIT_FIELD_REPRESENTATIVE (expr); + if (!tree_fits_uhwi_p (DECL_FIELD_OFFSET (expr)) + || !tree_fits_uhwi_p (DECL_FIELD_BIT_OFFSET (expr)) + || !tree_fits_uhwi_p (DECL_SIZE (expr))) + return false; + bitpos = tree_to_uhwi (DECL_FIELD_OFFSET (expr)) * BITS_PER_UNIT + + tree_to_uhwi (DECL_FIELD_BIT_OFFSET (expr)); + bitsize = tree_to_uhwi (DECL_SIZE (expr)); + } + else + { + if (!tree_fits_uhwi_p (TREE_OPERAND (expr, 2)) + || !tree_fits_uhwi_p (TREE_OPERAND (expr, 1))) + return false; + bitpos = tree_to_uhwi (TREE_OPERAND (expr, 2)); + bitsize = tree_to_uhwi (TREE_OPERAND (expr, 1)); + } + if (bitpos < 0 || bitsize <= 0) + return false; + size = (bitpos % BITS_PER_UNIT + bitsize + BITS_PER_UNIT - 1) + / BITS_PER_UNIT; + align = get_object_alignment (base); + if (align < BITS_PER_UNIT) + return false; + bitpos = bitpos & ~(BITS_PER_UNIT - 1); + if ((align - 1) & bitpos) + { + align = (align - 1) & bitpos; + align = align & -align; + } + gcc_checking_assert (is_gimple_addressable (base)); + expr = build_fold_addr_expr (unshare_expr (base)); + if (!is_gimple_mem_ref_addr (expr)) + { + g = gimple_build_assign (make_ssa_name (TREE_TYPE (expr)), expr); + expr = gimple_assign_lhs (g); + gimple_set_location (g, loc); + gimple_seq_add_stmt_without_update (&seq, g); + } + expr = build2 (MEM_REF, char_type_node, expr, + build_int_cst (TREE_TYPE (expr), bitpos / BITS_PER_UNIT)); + expr_ptr = build_fold_addr_expr (expr); + } + else + { + align = get_object_alignment (expr); + if (align < BITS_PER_UNIT) + return false; + gcc_checking_assert (is_gimple_addressable (expr)); + expr_ptr = build_fold_addr_expr (unshare_expr (expr)); + } if (!is_gimple_val (expr_ptr)) { g = gimple_build_assign (make_ssa_name (TREE_TYPE (expr_ptr)), expr_ptr); @@ -173,7 +227,15 @@ instrument_expr (gimple_stmt_iterator gsi, tree expr, bool is_write) gimple_set_location (g, loc); gimple_seq_add_stmt_without_update (&seq, g); } - if (rhs == NULL) + if ((size & (size - 1)) == 0 || size > 16 + || align < MIN (size, 8) * BITS_PER_UNIT) + { + builtin_decl = builtin_decl_implicit (is_write + ? BUILT_IN_TSAN_WRITE_RANGE + : BUILT_IN_TSAN_READ_RANGE); + g = gimple_build_call (builtin_decl, 2, expr_ptr, size_int (size)); + } + else if (rhs == NULL) g = gimple_build_call (get_memory_access_decl (is_write, size), 1, expr_ptr); else |