16 using namespace SVFUtil;
32 return mhp->mayHappenInParallel(inst1, inst2);
45 validator.
init(mhp->getTCT()->getSVFModule());
50 if (!collectCallsiteTargets())
52 if (!collectCxtThreadTargets())
55 errstring = getOutput(
"Validate CxtThread:", validateCxtThread());
56 outs() <<
"======" << errstring <<
"======\n";
58 if (!collectTCTTargets())
60 errstring = getOutput(
"Validate TCT: ", validateTCT());
61 outs() <<
"======" << errstring <<
"======\n";
63 if (!collectInterleavingTargets())
65 errstring = getOutputforInterlevAnalysis(
"Validate Interleaving:", validateInterleaving());
66 outs() <<
"======" << errstring <<
"======\n";
71 std::stringstream ss(s);
73 while (std::getline(ss,
item, delim))
75 elems.push_back(
item);
82 std::vector<std::string> elems;
83 split(s, delim, elems);
90 const ConstantInt* x = SVFUtil::dyn_cast<ConstantInt>(cs->getArgOperand(arg_num));
91 assert((arg_num < cs->arg_size()) &&
"Does not has this argument");
92 return (
NodeID) x->getSExtValue();
99 assert((arg_num < cs->arg_size()) &&
"Does not has this argument");
100 const Constant* arrayinst = SVFUtil::dyn_cast<Constant>(cs->getArgOperand(arg_num));
101 if(
const GetElementPtrInst* gepinst = SVFUtil::dyn_cast<GetElementPtrInst>(cs->getArgOperand(arg_num)))
103 arrayinst = SVFUtil::dyn_cast<Constant>(gepinst->getOperand(0));
105 const ConstantDataArray* cxtarray = SVFUtil::dyn_cast<ConstantDataArray>(arrayinst->getOperand(0));
108 std::vector<std::string> strvec;
111 const std::string vthdcxtstring = cxtarray->getAsCString().str();
112 return split(vthdcxtstring,
',');
117 std::vector<std::string> x = getStringArg(inst, arg_num);
122 for (std::vector<std::string>::iterator i = x.begin(); i != x.end(); i++)
124 std::vector<std::string> y =
split((*i),
'.');
125 y[0].erase(y[0].find(
"cs"), 2);
127 const SVFFunction* callee = mod->getSVFFunction(y[1]);
128 const SVFInstruction* svfInst = csnumToInstMap[atoi(y[0].c_str())];
129 assert(callee &&
"callee error");
130 CallICFGNode* cbn = mhp->getTCT()->getCallICFGNode(svfInst);
131 CallSiteID csId = tcg->getCallSiteID(cbn, callee);
139 I = I->getPrevNode();
142 if (SVFUtil::isa<LoadInst>(I) || SVFUtil::isa<StoreInst>(I))
144 I = I->getPrevNode();
170 case INTERLEV_UNSOUND:
173 case INTERLEV_IMPRECISE:
184 if (cxt1.size() != cxt2.size())
186 return std::equal(cxt1.begin(), cxt1.end(), cxt2.begin());
192 std::stringstream rawstr(str);
194 for (CallStrCxt::const_iterator it = cxt.begin(), eit = cxt.end(); it != eit; ++it)
196 rawstr <<
" ' " << *it <<
" ' ";
197 rawstr << tcg->getCallSite(*it)->getCallSite()->toString();
198 rawstr <<
" call " << tcg->getCallSite(*it)->getCaller()->getName() <<
"-->" << tcg->getCalleeOfCallSite(*it)->getName() <<
", \n";
201 outs() <<
"max cxt = " << cxt.size() << rawstr.str() <<
"\n";
210 outs() << rthdTovthd[id] <<
", ";
219 for (Module::const_iterator
F = M.begin(), E = M.end();
F != E; ++
F)
221 for (Function::const_iterator bi = (*F).begin(), ebi = (*F).end(); bi != ebi; ++bi)
224 if (!bb->getName().str().compare(0, 2,
"cs"))
226 NodeID csnum = atoi(bb->getName().str().substr(2).c_str());
230 if (SVFUtil::isa<CallInst>(inst))
234 inst = inst->getNextNode();
235 assert(inst &&
"Wrong cs label, cannot find callsite");
238 csnumToInstMap[csnum] = svfInst;
243 return !csnumToInstMap.empty();
251 for(
auto it = M.begin(); it != M.end(); it++)
254 if(fName.find(CXT_THREAD) != std::string::npos)
266 vthdToCxt[0] = main_cxt;
270 for (Value::const_use_iterator it =
F->use_begin(), ie =
F->use_end(); it != ie; ++it)
273 const Value* user = u->getUser();
274 const Instruction* inst = SVFUtil::dyn_cast<Instruction>(user);
276 NodeID vthdnum = getIntArg(inst, 0);
279 vthdToCxt[vthdnum] = cxt;
291 for(
auto it = M.begin(); it != M.end(); it++)
294 if(fName.find(TCT_ACCESS) != std::string::npos)
304 for (Value::const_use_iterator it =
F->use_begin(), ie =
F->use_end(); it != ie; ++it)
307 const Value* user = u->getUser();
308 const Instruction* inst = SVFUtil::dyn_cast<Instruction>(user);
310 NodeID vthdnum = getIntArg(inst, 0);
311 NodeID rthdnum = vthdTorthd[vthdnum];
312 std::vector<std::string> x = getStringArg(inst, 1);
314 for (std::vector<std::string>::iterator i = x.begin(); i != x.end(); i++)
316 rthdToChildren[rthdnum].insert(vthdTorthd[atoi((*i).c_str())]);
329 for(
auto it = M.begin(); it != M.end(); it++)
332 if(fName.find(INTERLEV_ACCESS) != std::string::npos)
342 for (Value::const_use_iterator it =
F->use_begin(), ie =
F->use_end(); it != ie; ++it)
345 const Value* user = u->getUser();
346 const Instruction* inst = SVFUtil::dyn_cast<Instruction>(user);
348 NodeID vthdnum = getIntArg(inst, 0);
349 NodeID rthdnum = vthdTorthd[vthdnum];
351 std::vector<std::string> y = getStringArg(inst, 2);
358 for (std::vector<std::string>::iterator i = y.begin(); i != y.end(); i++)
360 lev.
set(vthdTorthd[atoi((*i).c_str())]);
363 const Instruction* memInst = getPreviousMemoryAccessInst(inst);
366 instToTSMap[svfMemInst].insert(cts);
367 threadStmtToInterLeaving[cts] = lev;
376 TCT* tct = mhp->getTCT();
382 outs() <<
errMsg(
"\nValidate CxtThread: The number of CxtThread is different from given result!!!\n");
383 outs() <<
"Given threads:\t" << vthdToCxt.size() <<
"\nAnalysis result:\t" << tct->
getTCTNodeNum() <<
"\n";
384 assert(
false &&
"test case failed!");
393 bool matched =
false;
396 NodeID vthdid = (*j).first;
397 if (matchCxt(rthd.
getContext(), vthdToCxt[vthdid]))
399 if (visitedvthd.find(vthdid) != visitedvthd.end())
404 outs() <<
"\nValidate CxtThread: Repeat real CxtThread !!!\n";
409 vthdTorthd[vthdid] = i;
410 rthdTovthd[i] = vthdid;
411 visitedvthd.insert(vthdid);
423 assert(
false &&
"test case failed!");
427 if (visitedvthd.size() != vthdToCxt.size())
432 SVFUtil::errs() <<
errMsg(
"\nValidate CxtThread: Some given CxtThreads cannot be found !!!\n");
433 assert(
false &&
"test case failed!");
436 NodeID vthdid = (*j).first;
437 if (visitedvthd.find(vthdid) == visitedvthd.end())
439 dumpCxt(vthdToCxt[vthdid]);
451 TCT* tct = mhp->getTCT();
454 bool res_node =
true;
459 NodeID tid = (*ci)->getDstID();
460 if (rthdToChildren[i].find(tid) == rthdToChildren[i].end())
467 for (
Set<NodeID>::iterator j = rthdToChildren[i].begin(), ej = rthdToChildren[i].end(); j != ej; j++)
478 outs() <<
errMsg(
"\nValidate TCT: Wrong at TID ") << rthdTovthd[i] <<
"\n";
479 outs() <<
"Given children: \t";
480 for (
Set<NodeID>::iterator j = rthdToChildren[i].begin(), ej = rthdToChildren[i].end(); j != ej; j++)
483 outs() << rthdTovthd[gid] <<
", ";
485 outs() <<
"\nAnalysis children:\t";
489 NodeID tid = (*ci)->getDstID();
490 outs() << rthdTovthd[tid] <<
", ";
502 for (MHP::InstToThreadStmtSetMap::iterator seti = instToTSMap.begin(), eseti = instToTSMap.end(); seti != eseti; ++seti)
508 if ((*seti).second.size() != tsSet.size())
513 outs() <<
"Reason: The number of thread running on stmt is wrong\n";
514 outs() <<
"\n----Given threads:\n";
515 for (MHP::CxtThreadStmtSet::iterator thdlevi = (*seti).second.begin(), ethdlevi = (*seti).second.end(); thdlevi != ethdlevi;
518 outs() <<
"TID " << rthdTovthd[(*thdlevi).getTid()] <<
": ";
519 dumpCxt((*thdlevi).getContext());
521 outs() <<
"\n----Analysis threads:\n";
522 for (MHP::CxtThreadStmtSet::const_iterator it = tsSet.begin(), eit = tsSet.end(); it != eit; ++it)
524 outs() <<
"TID " << rthdTovthd[(*it).getTid()] <<
": ";
525 dumpCxt((*it).getContext());
532 for (MHP::CxtThreadStmtSet::const_iterator it = tsSet.begin(), eit = tsSet.end(); it != eit; ++it)
535 bool matched =
false;
536 for (MHP::CxtThreadStmtSet::iterator it2 = (*seti).second.begin(), eit2 = (*seti).second.end(); it2 != eit2; ++it2)
543 NodeBS lev = mhp->getInterleavingThreads(ts);
544 NodeBS lev2 = threadStmtToInterLeaving[ts2];
550 outs() <<
"Reason: thread interleaving on stmt is wrong\n";
552 outs() <<
"Given result: \tTID " << rthdTovthd[ts.
getTid()];
554 outs() <<
"Analysis result: \tTID " << rthdTovthd[ts.
getTid()];
563 bool findeveryelement =
true;
568 findeveryelement =
false;
572 if (!findeveryelement)
586 outs() <<
"Reason: analysis thread cxt is not matched by given thread cxt\n";
588 NodeBS lev = mhp->getInterleavingThreads(ts);
590 outs() <<
"Analysis result: \tTID " << rthdTovthd[ts.
getTid()];
603 std::vector<const CallBase*> csInsts;
607 for(
auto it = M.begin(); it != M.end(); it++)
610 if(fName.find(RC_ACCESS) != std::string::npos)
619 for (Value::const_use_iterator it =
F->use_begin(), ie =
620 F->use_end(); it != ie; ++it)
623 const Value *user = u->getUser();
627 csInsts.push_back(csInst);
630 assert(csInsts.size() % 2 == 0 &&
"We should have RC_ACCESS called in pairs.");
633 std::sort(csInsts.begin(), csInsts.end(), compare);
636 for (
int i = 0, e = csInsts.size(); i != e;)
640 const ConstantInt* C = SVFUtil::dyn_cast<ConstantInt>(CI1->getArgOperand(1));
642 const Instruction* I1 = getPreviousMemoryAccessInst(CI1);
643 const Instruction* I2 = getPreviousMemoryAccessInst(CI2);
644 assert(I1 && I2 &&
"RC_ACCESS should be placed immediately after the target memory access.");
645 RC_FLAG flags = C->getZExtValue();
646 accessPairs.push_back(
AccessPair(I1, I2, flags));
655 for (
int i = 0, e = accessPairs.size(); i != e; ++i)
661 bool mhp = mayHappenInParallel(I1, I2);
662 bool alias = mayAccessAliases(I1, I2);
663 bool protect = protectedByCommonLocks(I1, I2);
664 bool racy = mayHaveDataRace(I1, I2);
669 if (selectedValidationScenarios & RC_ALIASES)
672 << getOutput(
"ALIASES", alias, ap.
isFlaged(RC_ALIASES))
675 if (selectedValidationScenarios & RC_MHP)
678 << getOutput(
"MHP", mhp, ap.
isFlaged(RC_MHP)) <<
"\n";
680 if (selectedValidationScenarios & RC_PROTECTED)
683 << getOutput(
"PROTECT", protect,
686 if (selectedValidationScenarios & RC_RACE)
689 << getOutput(
"RACE", racy, ap.
isFlaged(RC_RACE))
699 I = I->getPrevNode();
702 if (SVFUtil::isa<LoadInst>(I) || SVFUtil::isa<StoreInst>(I))
709 if (callee->getName().find(
"llvm.memset") != std::string::npos)
713 I = I->getPrevNode();
const CallStrCxt & getContext() const
Return current context.
NodeID getTid() const
Return current context.
void dump() const
Dump CxtThread.
const CallStrCxt & getContext() const
Return context of the thread.
static LLVMModuleSet * getLLVMModuleSet()
SVFInstruction * getSVFInstruction(const Instruction *inst) const
SVFValue * getSVFValue(const Value *value)
bool mayHappenInParallel(const Instruction *I1, const Instruction *I2)
Set< CxtThreadStmt > CxtThreadStmtSet
static const INTERLEV_FLAG INTERLEV_UNSOUND
std::vector< std::string > getStringArg(const Instruction *inst, unsigned int arg_num)
void dumpInterlev(NodeBS &lev)
bool collectCallsiteTargets()
INTERLEV_FLAG validateInterleaving()
bool collectInterleavingTargets()
bool collectCxtThreadTargets()
static const INTERLEV_FLAG INTERLEV_TRUE
Constant INTERLEV_FLAG values.
bool matchCxt(const CallStrCxt cxt1, const CallStrCxt cxt2) const
std::vector< std::string > & split(const std::string &s, char delim, std::vector< std::string > &elems)
static const INTERLEV_FLAG INTERLEV_IMPRECISE
std::string getOutput(const char *scenario, bool analysisRes)
const Instruction * getPreviousMemoryAccessInst(const Instruction *I)
std::string getOutputforInterlevAnalysis(const char *scenario, INTERLEV_FLAG analysisRes)
NodeID getIntArg(const Instruction *inst, unsigned int arg_num)
void dumpCxt(const CallStrCxt &cxt) const
CallStrCxt getCxtArg(const Instruction *inst, unsigned int arg_num)
static const Option< bool > PrintValidRes
bool isFlaged(const RC_FLAG flag) const
Class member access.
const Instruction * getInstruction1() const
const Instruction * getInstruction2() const
Validate the result of concurrent analysis.
void collectValidationTargets()
void validateAll()
Perform validation for all targets.
const Instruction * getPreviousMemoryAccessInst(const Instruction *I)
void init(SVFModule *M)
Initialization.
virtual const std::string getSourceLoc() const
bool test(unsigned Idx) const
const CxtThread & getCxtThread() const
Get CxtThread.
ThreadCreateEdgeSet::const_iterator getChildrenBegin(const TCTNode *node) const
Get children and parent nodes.
TCTNode * getTCTNode(NodeID id) const
Get TCT node.
TCTEdge * hasGraphEdge(TCTNode *src, TCTNode *dst, TCTEdge::CEDGEK kind) const
Whether we have already created this call graph edge.
u32_t getTCTNodeNum() const
Get Statistics.
ThreadCreateEdgeSet::const_iterator getChildrenEnd(const TCTNode *node) const
const CallBase * getLLVMCallSite(const Value *value)
Return LLVM callsite given a value.
bool isCallSite(const Instruction *inst)
Whether an instruction is a call or invoke instruction.
std::string sucMsg(const std::string &msg)
Returns successful message by converting a string into green string output.
std::string bugMsg1(const std::string &msg)
const SVFFunction * getCallee(const CallSite cs)
Return callee of a callsite. Return null if this is an indirect call.
std::string pasMsg(const std::string &msg)
Print each pass/phase message by converting a string into blue string output.
std::string errMsg(const std::string &msg)
Print error message by converting a string into red string output.
std::ostream & errs()
Overwrite llvm::errs()
std::string bugMsg2(const std::string &msg)
std::vector< std::string > split(const std::string &s, char separator)
Split into two substrings around the first occurrence of a separator string.
std::ostream & outs()
Overwrite llvm::outs()
llvm::BasicBlock BasicBlock
llvm::Instruction Instruction
std::unordered_map< Key, Value, Hash, KeyEqual, Allocator > Map
llvm::Value Value
LLVM Basic classes.
std::vector< u32_t > CallStrCxt
llvm::GetElementPtrInst GetElementPtrInst
llvm::ConstantDataArray ConstantDataArray
llvm::ConstantInt ConstantInt
std::unordered_set< Key, Hash, KeyEqual, Allocator > Set