ThreadSanitizer.cpp revision 6e590e3f61b101554f97d6ab257c802c9ec49862
160ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany//===-- ThreadSanitizer.cpp - race detector -------------------------------===//
260ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany//
360ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany//                     The LLVM Compiler Infrastructure
460ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany//
560ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany// This file is distributed under the University of Illinois Open Source
660ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany// License. See LICENSE.TXT for details.
760ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany//
860ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany//===----------------------------------------------------------------------===//
960ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany//
1060ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany// This file is a part of ThreadSanitizer, a race detector.
1160ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany//
1260ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany// The tool is under development, for the details about previous versions see
1360ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany// http://code.google.com/p/data-race-test
1460ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany//
1560ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany// The instrumentation phase is quite simple:
1660ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany//   - Insert calls to run-time library before every memory access.
1760ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany//      - Optimizations may apply to avoid instrumenting some of the accesses.
1860ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany//   - Insert calls at function entry/exit.
1960ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany// The rest is handled by the run-time library.
2060ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany//===----------------------------------------------------------------------===//
2160ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany
2260ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany#define DEBUG_TYPE "tsan"
2360ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany
246e590e3f61b101554f97d6ab257c802c9ec49862Kostya Serebryany#include "FunctionBlackList.h"
2560ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany#include "llvm/ADT/SmallString.h"
2660ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany#include "llvm/ADT/SmallVector.h"
2760ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany#include "llvm/ADT/StringExtras.h"
2860ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany#include "llvm/Intrinsics.h"
2960ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany#include "llvm/Function.h"
3060ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany#include "llvm/Module.h"
316e590e3f61b101554f97d6ab257c802c9ec49862Kostya Serebryany#include "llvm/Support/CommandLine.h"
3260ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany#include "llvm/Support/Debug.h"
3360ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany#include "llvm/Support/IRBuilder.h"
3460ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany#include "llvm/Support/MathExtras.h"
3560ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany#include "llvm/Target/TargetData.h"
3660ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany#include "llvm/Transforms/Instrumentation.h"
3760ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany#include "llvm/Transforms/Utils/ModuleUtils.h"
3860ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany#include "llvm/Type.h"
3960ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany
4060ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryanyusing namespace llvm;
4160ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany
426e590e3f61b101554f97d6ab257c802c9ec49862Kostya Serebryanystatic cl::opt<std::string>  ClBlackListFile("tsan-blacklist",
436e590e3f61b101554f97d6ab257c802c9ec49862Kostya Serebryany       cl::desc("Blacklist file"), cl::Hidden);
446e590e3f61b101554f97d6ab257c802c9ec49862Kostya Serebryany
4560ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryanynamespace {
4660ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany/// ThreadSanitizer: instrument the code in module to find races.
4760ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryanystruct ThreadSanitizer : public FunctionPass {
4860ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  ThreadSanitizer();
4960ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  bool runOnFunction(Function &F);
5060ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  bool doInitialization(Module &M);
5160ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  bool instrumentLoadOrStore(Instruction *I);
5260ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  static char ID;  // Pass identification, replacement for typeid.
5360ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany
5460ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany private:
5560ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  TargetData *TD;
566e590e3f61b101554f97d6ab257c802c9ec49862Kostya Serebryany  OwningPtr<FunctionBlackList> BL;
5760ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  // Callbacks to run-time library are computed in doInitialization.
5860ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  Value *TsanFuncEntry;
5960ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  Value *TsanFuncExit;
6060ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  // Accesses sizes are powers of two: 1, 2, 4, 8, 16.
613eccaa6625a8032bee6b84706cb46ed8eb915acfKostya Serebryany  static const size_t kNumberOfAccessSizes = 5;
6260ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  Value *TsanRead[kNumberOfAccessSizes];
6360ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  Value *TsanWrite[kNumberOfAccessSizes];
6460ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany};
6560ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany}  // namespace
6660ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany
6760ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryanychar ThreadSanitizer::ID = 0;
6860ebb1947faed42e493179e569c5db0c01d38a2aKostya SerebryanyINITIALIZE_PASS(ThreadSanitizer, "tsan",
6960ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany    "ThreadSanitizer: detects data races.",
7060ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany    false, false)
7160ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany
7260ebb1947faed42e493179e569c5db0c01d38a2aKostya SerebryanyThreadSanitizer::ThreadSanitizer()
7360ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  : FunctionPass(ID),
7460ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  TD(NULL) {
7560ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany}
7660ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany
7760ebb1947faed42e493179e569c5db0c01d38a2aKostya SerebryanyFunctionPass *llvm::createThreadSanitizerPass() {
7860ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  return new ThreadSanitizer();
7960ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany}
8060ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany
8160ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryanybool ThreadSanitizer::doInitialization(Module &M) {
8260ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  TD = getAnalysisIfAvailable<TargetData>();
8360ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  if (!TD)
8460ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany    return false;
856e590e3f61b101554f97d6ab257c802c9ec49862Kostya Serebryany  BL.reset(new FunctionBlackList(ClBlackListFile));
866e590e3f61b101554f97d6ab257c802c9ec49862Kostya Serebryany
8760ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  // Always insert a call to __tsan_init into the module's CTORs.
8860ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  IRBuilder<> IRB(M.getContext());
8960ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  Value *TsanInit = M.getOrInsertFunction("__tsan_init",
9060ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany                                          IRB.getVoidTy(), NULL);
9160ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  appendToGlobalCtors(M, cast<Function>(TsanInit), 0);
9260ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany
9360ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  // Initialize the callbacks.
9460ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  TsanFuncEntry = M.getOrInsertFunction("__tsan_func_entry", IRB.getVoidTy(),
9560ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany                                        IRB.getInt8PtrTy(), NULL);
9660ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  TsanFuncExit = M.getOrInsertFunction("__tsan_func_exit", IRB.getVoidTy(),
9760ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany                                       NULL);
983eccaa6625a8032bee6b84706cb46ed8eb915acfKostya Serebryany  for (size_t i = 0; i < kNumberOfAccessSizes; ++i) {
9960ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany    SmallString<32> ReadName("__tsan_read");
10060ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany    ReadName += itostr(1 << i);
10160ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany    TsanRead[i] = M.getOrInsertFunction(ReadName, IRB.getVoidTy(),
10260ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany                                        IRB.getInt8PtrTy(), NULL);
10360ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany    SmallString<32> WriteName("__tsan_write");
10460ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany    WriteName += itostr(1 << i);
10560ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany    TsanWrite[i] = M.getOrInsertFunction(WriteName, IRB.getVoidTy(),
10660ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany                                         IRB.getInt8PtrTy(), NULL);
10760ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  }
10860ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  return true;
10960ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany}
11060ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany
11160ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryanybool ThreadSanitizer::runOnFunction(Function &F) {
11260ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  if (!TD) return false;
1136e590e3f61b101554f97d6ab257c802c9ec49862Kostya Serebryany  if (BL->isIn(F)) return false;
11460ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  SmallVector<Instruction*, 8> RetVec;
11560ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  SmallVector<Instruction*, 8> LoadsAndStores;
11660ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  bool Res = false;
11760ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  bool HasCalls = false;
11860ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany
11960ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  // Traverse all instructions, collect loads/stores/returns, check for calls.
12060ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  for (Function::iterator FI = F.begin(), FE = F.end();
12160ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany       FI != FE; ++FI) {
12260ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany    BasicBlock &BB = *FI;
12360ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany    for (BasicBlock::iterator BI = BB.begin(), BE = BB.end();
12460ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany         BI != BE; ++BI) {
12560ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany      if (isa<LoadInst>(BI) || isa<StoreInst>(BI))
12660ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany        LoadsAndStores.push_back(BI);
12760ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany      else if (isa<ReturnInst>(BI))
12860ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany        RetVec.push_back(BI);
12960ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany      else if (isa<CallInst>(BI) || isa<InvokeInst>(BI))
13060ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany        HasCalls = true;
13160ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany    }
13260ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  }
13360ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany
13460ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  // We have collected all loads and stores.
13560ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  // FIXME: many of these accesses do not need to be checked for races
13660ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  // (e.g. variables that do not escape, etc).
13760ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany
13860ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  // Instrument memory accesses.
13960ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  for (size_t i = 0, n = LoadsAndStores.size(); i < n; ++i) {
14060ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany    Res |= instrumentLoadOrStore(LoadsAndStores[i]);
14160ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  }
14260ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany
14360ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  // Instrument function entry/exit points if there were instrumented accesses.
14460ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  if (Res || HasCalls) {
14560ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany    IRBuilder<> IRB(F.getEntryBlock().getFirstNonPHI());
14660ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany    Value *ReturnAddress = IRB.CreateCall(
14760ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany        Intrinsic::getDeclaration(F.getParent(), Intrinsic::returnaddress),
14860ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany        IRB.getInt32(0));
14960ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany    IRB.CreateCall(TsanFuncEntry, ReturnAddress);
15060ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany    for (size_t i = 0, n = RetVec.size(); i < n; ++i) {
15160ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany      IRBuilder<> IRBRet(RetVec[i]);
15260ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany      IRBRet.CreateCall(TsanFuncExit);
15360ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany    }
15460ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  }
15560ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  return Res;
15660ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany}
15760ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany
15860ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryanybool ThreadSanitizer::instrumentLoadOrStore(Instruction *I) {
15960ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  IRBuilder<> IRB(I);
16060ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  bool IsWrite = isa<StoreInst>(*I);
16160ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  Value *Addr = IsWrite
16260ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany      ? cast<StoreInst>(I)->getPointerOperand()
16360ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany      : cast<LoadInst>(I)->getPointerOperand();
16460ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  Type *OrigPtrTy = Addr->getType();
16560ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  Type *OrigTy = cast<PointerType>(OrigPtrTy)->getElementType();
16660ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  assert(OrigTy->isSized());
16760ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  uint32_t TypeSize = TD->getTypeStoreSizeInBits(OrigTy);
16860ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  if (TypeSize != 8  && TypeSize != 16 &&
16960ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany      TypeSize != 32 && TypeSize != 64 && TypeSize != 128) {
17060ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany    // Ignore all unusual sizes.
17160ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany    return false;
17260ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  }
1733eccaa6625a8032bee6b84706cb46ed8eb915acfKostya Serebryany  size_t Idx = CountTrailingZeros_32(TypeSize / 8);
17460ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  assert(Idx < kNumberOfAccessSizes);
17560ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  Value *OnAccessFunc = IsWrite ? TsanWrite[Idx] : TsanRead[Idx];
17660ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  IRB.CreateCall(OnAccessFunc, IRB.CreatePointerCast(Addr, IRB.getInt8PtrTy()));
17760ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  return true;
17860ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany}
179