llvm.org GIT mirror llvm / 0a20d99
[tsan] Do not instrument reads/writes to instruction profile counters. We have known races on profile counters, which can be reproduced by enabling -fsanitize=thread and -fprofile-instr-generate simultaneously on a multi-threaded program. This patch avoids reporting those races by not instrumenting the reads and writes coming from the instruction profiler. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@264805 91177308-0d34-0410-b5e6-96231b3b80d8 Anna Zaks 4 years ago
2 changed file(s) with 58 addition(s) and 1 deletion(s). Raw diff Collapse all Expand all
3535 #include "llvm/IR/Metadata.h"
3636 #include "llvm/IR/Module.h"
3737 #include "llvm/IR/Type.h"
38 #include "llvm/ProfileData/InstrProf.h"
3839 #include "llvm/Support/CommandLine.h"
3940 #include "llvm/Support/Debug.h"
4041 #include "llvm/Support/MathExtras.h"
242243 return false;
243244 }
244245
246 // Do not instrument known races/"benign races" that come from compiler
247 // instrumentatin. The user has no way of suppressing them.
248 bool shouldInstrumentReadWriteFromAddress(Value *Addr) {
249 // Peel off GEPs and BitCasts.
250 Addr = Addr->stripInBoundsOffsets();
251
252 if (GlobalVariable *GV = dyn_cast(Addr)) {
253 if (GV->hasSection()) {
254 StringRef SectionName = GV->getSection();
255 // Check if the global is in the PGO counters section.
256 if (SectionName.endswith(getInstrProfCountersSectionName(
257 /*AddSegment=*/false)))
258 return false;
259 }
260 }
261 return true;
262 }
263
245264 bool ThreadSanitizer::addrPointsToConstantData(Value *Addr) {
246265 // If this is a GEP, just analyze its pointer operand.
247266 if (GetElementPtrInst *GEP = dyn_cast(Addr))
284303 E = Local.rend(); It != E; ++It) {
285304 Instruction *I = *It;
286305 if (StoreInst *Store = dyn_cast(I)) {
287 WriteTargets.insert(Store->getPointerOperand());
306 Value *Addr = Store->getPointerOperand();
307 if (!shouldInstrumentReadWriteFromAddress(Addr))
308 continue;
309 WriteTargets.insert(Addr);
288310 } else {
289311 LoadInst *Load = cast(I);
290312 Value *Addr = Load->getPointerOperand();
313 if (!shouldInstrumentReadWriteFromAddress(Addr))
314 continue;
291315 if (WriteTargets.count(Addr)) {
292316 // We will write to this temp, so no reason to analyze the read.
293317 NumOmittedReadsBeforeWrite++;
0 ; This test checks that we are not instrumenting unwanted acesses to globals:
1 ; - Instruction profiler counter instrumentation has known intended races.
2 ;
3 ; RUN: opt < %s -tsan -S | FileCheck %s
4
5 target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
6 target triple = "x86_64-apple-macosx10.9"
7
8 @__profc_test_gep = private global [1 x i64] zeroinitializer, section "__DATA,__llvm_prf_cnts", align 8
9 @__profc_test_bitcast = private global [2 x i64] zeroinitializer, section "__DATA,__llvm_prf_cnts", align 8
10 @__profc_test_bitcast_foo = private global [1 x i64] zeroinitializer, section "__DATA,__llvm_prf_cnts", align 8
11
12 define i32 @test_gep() sanitize_thread {
13 entry:
14 %pgocount = load i64, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc_test_gep, i64 0, i64 0)
15 %0 = add i64 %pgocount, 1
16 store i64 %0, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc_test_gep, i64 0, i64 0)
17 ret i32 1
18 }
19
20 define i32 @test_bitcast() sanitize_thread {
21 entry:
22 %0 = load <2 x i64>, <2 x i64>* bitcast ([2 x i64]* @__profc_test_bitcast to <2 x i64>*), align 8
23 %.promoted5 = load i64, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc_test_bitcast_foo, i64 0, i64 0), align 8
24 %1 = add i64 %.promoted5, 10
25 %2 = add <2 x i64> %0,
26 store <2 x i64> %2, <2 x i64>* bitcast ([2 x i64]* @__profc_test_bitcast to <2 x i64>*), align 8
27 store i64 %1, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc_test_bitcast_foo, i64 0, i64 0), align 8
28 ret i32 undef
29 }
30
31 ; CHECK-NOT: {{call void @__tsan_write}}
32 ; CHECK: __tsan_init