Static Value-Flow Analysis
LockResultValidator.cpp
Go to the documentation of this file.
1 /*
2  * LOCKResultValidator.cpp
3  *
4  * Created on: 24/07/2021
5  */
6 
7 #include "Util/Options.h"
8 #include <string>
9 #include <sstream>
10 #include "LockResultValidator.h"
11 #include "MTAResultValidator.h"
12 #include "SVF-LLVM/LLVMModule.h"
13 
14 using namespace SVF;
15 using namespace SVFUtil;
16 
17 namespace SVF
18 {
19 
20 // Subclassing RCResultValidator to define the abstract methods.
22 {
23 public:
24  RaceValidator(LockAnalysis* lockAnalysis) :lsa(lockAnalysis)
25  {
26  }
27  bool protectedByCommonLocks(const Instruction* I1, const Instruction* I2)
28  {
31  return lsa->isProtectedByCommonLock(inst1, inst2);
32  }
33 private:
35 };
36 
37 } // End namespace SVF
38 
40 {
41  assert(LLVMUtil::isCallSite(inst) && "getFirstIntArg: inst is not a callsite");
42  const CallBase* cs = LLVMUtil::getLLVMCallSite(inst);
43  assert((arg_num < cs->arg_size()) && "Does not has this argument");
44  const GetElementPtrInst* gepinst = SVFUtil::dyn_cast<GetElementPtrInst>(cs->getArgOperand(arg_num));
45  const Constant* arrayinst = SVFUtil::dyn_cast<Constant>(gepinst->getOperand(0));
46  const ConstantDataArray* cxtarray = SVFUtil::dyn_cast<ConstantDataArray>(arrayinst->getOperand(0));
47  if (!cxtarray)
48  {
49  Set<std::string> strvec;
50  return strvec;
51  }
52  const std::string vthdcxtstring = cxtarray->getAsCString().str();
53  return split(vthdcxtstring, ',');
54 }
55 
57 {
58  std::stringstream ss(s);
60  while (std::getline(ss, item, delim))
61  {
62  elems.insert(item);
63  }
64  return elems;
65 }
66 
68 {
69  Set<std::string> elems;
70  split(s, delim, elems);
71  return elems;
72 }
73 
74 inline std::string LockResultValidator::getOutput(const char *scenario, LOCK_FLAG analysisRes)
75 {
76  std::string ret(scenario);
77  ret += "\t";
78  switch (analysisRes)
79  {
80  case LOCK_TRUE:
81  ret += SVFUtil::sucMsg("SUCCESS");
82  break;
83  case LOCK_UNSOUND:
84  ret += SVFUtil::bugMsg2("UNSOUND");
85  break;
86  case LOCK_IMPRECISE:
87  ret += SVFUtil::bugMsg1("IMPRECISE");
88  break;
89  default:
90  ret += SVFUtil::errMsg("FAILURE");
91  }
92  return ret;
93 }
94 
96 {
97  const Function* F = nullptr;
98  for (Module &M : LLVMModuleSet::getLLVMModuleSet()->getLLVMModules())
99  {
100  for(auto it = M.begin(); it != M.end(); it++)
101  {
102  const std::string fName = (*it).getName().str();
103  if(fName.find(LOCK) != std::string::npos)
104  {
105  F = &(*it);
106  break;
107  }
108  }
109  }
110  if (!F)
111  return false;
112  for(Value::const_use_iterator it = F->use_begin(), ie = F->use_end(); it!=ie; it++)
113  {
114  const Use *u = &*it;
115  const Value* user = u->getUser();
116  const Instruction* inst = SVFUtil::dyn_cast<Instruction>(user);
117  CxtLockSetStr y = getStringArg(inst, 0);
118  const Instruction* memInst = getPreviousMemoryAccessInst(inst);
119  const SVFInstruction* svfMemInst = LLVMModuleSet::getLLVMModuleSet()->getSVFInstruction(memInst);
120 
121  instToCxtLockSet[svfMemInst] = y;
122  if(const StoreInst* store = SVFUtil::dyn_cast<StoreInst> (memInst))
123  {
124  if(const BinaryOperator* bop = SVFUtil::dyn_cast<BinaryOperator> (store->getValueOperand()))
125  {
126  const Value* v = bop->getOperand(0);
127  const Instruction* prevInst = SVFUtil::dyn_cast<LoadInst> (v);
128  const SVFInstruction* svfPrevInst = LLVMModuleSet::getLLVMModuleSet()->getSVFInstruction(prevInst);
129  instToCxtLockSet[svfPrevInst] = y;
130  }
131  }
132  }
133  return true;
134 }
135 
137 {
138  SVFIR* pag = SVFIR::getPAG();
140  LockAnalysis::CxtStmtToCxtLockSet analyedLS = _la->getCSTCLS();
141  for(LockAnalysis::CxtStmtToCxtLockSet::iterator it = analyedLS.begin(),
142  eit = analyedLS.end(); it!=eit; it++)
143  {
144  const SVFInstruction* inst = ((*it).first).getStmt();
145  bool interestedInst = true;
146  for(const SVFStmt* stmt : pag->getSVFStmtList(pag->getICFG()->getICFGNode(inst)))
147  {
148  if(!SVFUtil::isa<LoadStmt>(stmt) && !SVFUtil::isa<StoreStmt>(stmt))
149  interestedInst = false;
150  }
151  if(interestedInst==false)
152  continue;
153  const SVFFunction* F = inst->getFunction();
154  if(inFilter(F->getName()))
155  continue;
156  CxtLockSetStr LS = instToCxtLockSet[inst];
157  if(LS.size() != (*it).second.size())
158  {
160  {
161  outs() << errMsg("\nValidate Stmt's Lock : Wrong at: ") << inst->toString() << "\n";
162  outs() << "Reason: The number of lock on current stmt is wrong\n";
163  outs() << "\n----Given locks:\n";
164  for (CxtLockSetStr::iterator it1 = LS.begin(),eit1 = LS.end(); it1 != eit1; it++)
165  {
166  outs() << "Lock " << *it1 << " ";
167  }
168  outs() << "\n----Analysis locks:\n";
169  for (LockAnalysis::CxtLockSet::iterator it2 = (*it).second.begin(),
170  eit2 = (*it).second.end(); it2 != eit2; ++it)
171  {
172  const SVFInstruction* call = (*it2).getStmt();
173  outs()<<"Lock " << call->toString() << " ";
174  }
175  outs() << "\n";
176  }
178  }
179  LockAnalysis::CxtLockSet LSA = (*it).second;
180 
181  for(LockAnalysis::CxtLockSet::iterator it3 = LSA.begin(), eit3=LSA.end(); it3!=eit3; it3++)
182  {
183  const SVFInstruction* call = (*it3).getStmt();
184  if(SVFUtil::isCallSite(call) == false)
185  continue;
187  if(!match(lockName, LS))
188  {
190  {
191  outs() << "\nValidate Stmt's Lock : Wrong at (" << inst->toString() << ")\n";
192  outs() << "Reason: The number of lock on current stmt is wrong\n";
193  outs() << "\n Lock " << lockName << " should not protect current instruction\n";
195  }
196  }
197  }
198  }
199  return res;
200 }
201 
203 {
204  outs() << SVFUtil::pasMsg(" --- Lock Analysis Result Validation ---\n");
205  if(!collectLockTargets())
206  return;
207  std::string errstring;
208  errstring = getOutput("Validate Lock Analysis :", validateStmtInLock());
209  outs() << "======" << errstring << "======\n";
210 
211  RaceValidator validator(_la);
212  validator.init(_la->getTCT()->getSVFModule());
213  validator.analyze();
214 }
215 
217 {
218  I = I->getPrevNode();
219  while (I)
220  {
221  if (SVFUtil::isa<LoadInst>(I) || SVFUtil::isa<StoreInst>(I))
222  return I;
223  SVFFunction* callee = nullptr;
224 
225  if(LLVMUtil::isCallSite(I))
226  {
229  _la->getTCT()->getThreadCallGraph()->getCallees(getCBN(svfInst), callees);
230 
231  for(PTACallGraph::FunctionSet::const_iterator cit = callees.begin(),
232  ecit = callees.end(); cit!=ecit; cit++)
233  {
234  if(*cit != nullptr)
235  {
236  callee = const_cast<SVFFunction*> (*cit);
237  break;
238  }
239 
240  }
241  }
242 
243  if (callee)
244  {
245  if (callee->getName().find("llvm.memset") != std::string::npos)
246  return I;
247  }
248  I = I->getPrevNode();
249  }
250  return nullptr;
251 }
#define F(f)
cJSON * item
Definition: cJSON.h:222
const char *const string
Definition: cJSON.h:172
const SVFValue * getArgOperand(u32_t i) const
Definition: SVFValue.h:1148
ICFGNode * getICFGNode(NodeID id) const
Get a ICFG node.
Definition: ICFG.h:92
static LLVMModuleSet * getLLVMModuleSet()
Definition: LLVMModule.h:105
SVFInstruction * getSVFInstruction(const Instruction *inst) const
Definition: LLVMModule.h:224
Set< CxtLock > CxtLockSet
Definition: LockAnalysis.h:70
Map< CxtStmt, CxtLockSet > CxtStmtToCxtLockSet
Definition: LockAnalysis.h:76
static const LOCK_FLAG LOCK_TRUE
static const LOCK_FLAG LOCK_UNSOUND
Set< std::string > getStringArg(const Instruction *inst, unsigned int arg_num)
static const LOCK_FLAG LOCK_IMPRECISE
const Instruction * getPreviousMemoryAccessInst(const Instruction *I)
std::string getOutput(const char *scenario, LOCK_FLAG analysisRes)
Set< std::string > & split(const std::string &s, char delim, Set< std::string > &elems)
Set< std::string > CxtLockSetStr
static const Option< bool > PrintValidRes
Definition: Options.h:175
Set< const SVFFunction * > FunctionSet
Definition: PTACallGraph.h:228
Validate the result of concurrent analysis.
void init(SVFModule *M)
Initialization.
RaceValidator(LockAnalysis *lockAnalysis)
bool protectedByCommonLocks(const Instruction *I1, const Instruction *I2)
static SVFIR * getPAG(bool buildFromFile=false)
Singleton design here to make sure we only have one instance during any analysis.
Definition: SVFIR.h:114
SVFStmtList & getSVFStmtList(const ICFGNode *inst)
Given an instruction, get all its PAGEdges.
Definition: SVFIR.h:208
ICFG * getICFG() const
Definition: SVFIR.h:170
const SVFFunction * getFunction() const
Definition: SVFValue.h:683
const std::string & getName() const
Definition: SVFValue.h:243
std::string toString() const
Needs to be implemented by a SVF front end.
Definition: LLVMUtil.cpp:906
const CallBase * getLLVMCallSite(const Value *value)
Return LLVM callsite given a value.
Definition: LLVMUtil.h:59
bool isCallSite(const Instruction *inst)
Whether an instruction is a call or invoke instruction.
Definition: LLVMUtil.h:45
std::string sucMsg(const std::string &msg)
Returns successful message by converting a string into green string output.
Definition: SVFUtil.cpp:53
std::string bugMsg1(const std::string &msg)
Definition: SVFUtil.cpp:81
std::string pasMsg(const std::string &msg)
Print each pass/phase message by converting a string into blue string output.
Definition: SVFUtil.cpp:99
std::string errMsg(const std::string &msg)
Print error message by converting a string into red string output.
Definition: SVFUtil.cpp:76
CallSite getSVFCallSite(const SVFInstruction *inst)
Return LLVM callsite given an instruction.
Definition: SVFUtil.h:196
std::string bugMsg2(const std::string &msg)
Definition: SVFUtil.cpp:86
std::vector< std::string > split(const std::string &s, char separator)
Split into two substrings around the first occurrence of a separator string.
Definition: SVFUtil.h:218
std::ostream & outs()
Overwrite llvm::outs()
Definition: SVFUtil.h:50
bool isCallSite(const SVFInstruction *inst)
Whether an instruction is a call or invoke instruction.
Definition: SVFUtil.h:174
for isBitcode
Definition: BasicTypes.h:68
llvm::CallBase CallBase
Definition: BasicTypes.h:146
llvm::Use Use
Definition: BasicTypes.h:72
llvm::Function Function
Definition: BasicTypes.h:85
llvm::Instruction Instruction
Definition: BasicTypes.h:87
llvm::Constant Constant
Definition: BasicTypes.h:124
llvm::Value Value
LLVM Basic classes.
Definition: BasicTypes.h:82
llvm::Module Module
Definition: BasicTypes.h:84
llvm::BinaryOperator BinaryOperator
Definition: BasicTypes.h:179
llvm::StoreInst StoreInst
Definition: BasicTypes.h:148
llvm::GetElementPtrInst GetElementPtrInst
Definition: BasicTypes.h:162
llvm::ConstantDataArray ConstantDataArray
Definition: BasicTypes.h:121
std::unordered_set< Key, Hash, KeyEqual, Allocator > Set
Definition: GeneralType.h:96