mirror of git://gcc.gnu.org/git/gcc.git
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
This commit is contained in:
parent
e4dd5b691d
commit
fe86867f07
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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)" } */
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
84
gcc/tsan.c
84
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
|
||||
|
|
|
|||
Loading…
Reference in New Issue