aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorBernd Edlinger <bernd.edlinger@hotmail.de>2015-01-02 22:16:59 +0000
committerBernd Edlinger <edlinger@gcc.gnu.org>2015-01-02 22:16:59 +0000
commitfe86867f07504f643ab9bf1147bac785222cadb0 (patch)
tree2e150e026804c390ac9333406e3d7552c6a62711 /gcc
parente4dd5b691d56f11c225e1e1847be3800854634b6 (diff)
downloadgcc-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/ChangeLog9
-rw-r--r--gcc/sanitizer.def4
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/c-c++-common/tsan/bitfield_race.c26
-rw-r--r--gcc/testsuite/g++.dg/tsan/aligned_vs_unaligned_race.C8
-rw-r--r--gcc/tsan.c84
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;
}
diff --git a/gcc/tsan.c b/gcc/tsan.c
index 678fcdc..7992a44 100644
--- a/gcc/tsan.c
+++ b/gcc/tsan.c
@@ -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