SVF
MTAResultValidator.h
Go to the documentation of this file.
1 /*
2  * MTAResultValidator.h
3  *
4  * Created on: 29/06/2015
5  * Author: Peng Di and Ding Ye
6  */
7 
8 #ifndef MTARESULTVALIDATOR_H_
9 #define MTARESULTVALIDATOR_H_
10 
12 #include "MTA/TCT.h"
13 #include "MTA/MHP.h"
14 #include "Util/SVFUtil.h"
15 #include "Graphs/ThreadCallGraph.h"
16 
22 {
23 
24 public:
25  typedef int INTERLEV_FLAG;
26  MTAResultValidator(MHP* mh) :
27  mhp(mh)
28  {
29  tcg = mhp->getThreadCallGraph();
30  tdAPI = tcg->getThreadAPI();
31  }
32  // Destructor
34  {
35  }
36 
37  // Analysis
38  void analyze();
39 
40 protected:
41 
42  /*
43  * Assistant functions
44  */
45 
46  // Split string
47  std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems);
48  std::vector<std::string> split(const std::string &s, char delim);
49 
50  // Get special arguments of given call sites
51  NodeID getIntArg(const Instruction* inst, unsigned int arg_num);
52  std::vector<std::string> getStringArg(const Instruction* inst, unsigned int arg_num);
53  CallStrCxt getCxtArg(const Instruction* inst, unsigned int arg_num);
54 
55  /*
56  * Get the previous LoadInst or StoreInst from Instruction "I" in the
57  * same BasicBlock. Return nullptr if none exists.
58  */
60 
61  // Compare two cxts
62  bool matchCxt(const CallStrCxt cxt1, const CallStrCxt cxt2) const;
63 
64  // Dump calling context information
65  void dumpCxt(const CallStrCxt& cxt) const;
66 
67  void dumpInterlev(NodeBS& lev);
68 
69  // Get the validation result string of a single validation scenario.
70  inline std::string getOutput(const char *scenario, bool analysisRes);
71  inline std::string getOutputforInterlevAnalysis(const char *scenario, INTERLEV_FLAG analysisRes);
72 
73  /*
74  * Collect the callsite targets for validations.
75  * The targets are labeled by "cs1:", "cs2:"... that are the names of its basic blocks.
76  * The collected targets are stored in csnumToInstMap that maps label "cs1" to CallInst.
77  */
79 
80  /*
81  * Collect the CxtThread targets for validations.
82  * The collected targets are stored in vthdToCxt that maps vthd to cxt.
83  */
85 
86  /*
87  * Collect TCT targets for validations.
88  * The collected targets are stored in rthdToChildren.
89  */
90  bool collectTCTTargets();
91 
92  /*
93  * Collect the thread interleaving targets for validations.
94  * The collected targets are stored in instToTSMap and threadStmtToInterLeaving.
95  */
97 
98  /*
99  * Perform validation for Cxtthread.
100  * If correct, the validator maps given thread vthd to static CxtThread rthd stored in vthdTorthd.
101  */
102  bool validateCxtThread();
103 
104  /*
105  * Perform validation for TCT.
106  */
107  bool validateTCT();
108 
109  /*
110  * Perform validation for thread interleaving.
111  */
112  INTERLEV_FLAG validateInterleaving();
113 
114 private:
115 
116  Map<NodeID, const CallInst*> csnumToInstMap;
117  Map<NodeID, CallStrCxt> vthdToCxt;
118  Map<NodeID, NodeID> vthdTorthd;
119  Map<NodeID, NodeID> rthdTovthd;
120 
121  Map<NodeID, Set<NodeID>> rthdToChildren;
122 
123  MHP::InstToThreadStmtSetMap instToTSMap; // Map a instruction to CxtThreadStmtSet
124  MHP::ThreadStmtToThreadInterleav threadStmtToInterLeaving;
125 
126  static constexpr char const *CXT_THREAD = "CXT_THREAD";
127  static constexpr char const *INTERLEV_ACCESS = "INTERLEV_ACCESS";
128  static constexpr char const *TCT_ACCESS = "TCT_ACCESS";
129 
130  ThreadAPI* tdAPI;
131  ThreadCallGraph* tcg;
132  MHP* mhp;
133 
135 
136  static const INTERLEV_FLAG INTERLEV_TRUE = 0x01;
137  static const INTERLEV_FLAG INTERLEV_IMPRECISE = 0x02;
138  static const INTERLEV_FLAG INTERLEV_UNSOUND = 0x04;
140 };
141 
142 
143 
160 {
161 public:
162  typedef int RC_FLAG;
163 
168  {
169  public:
171  AccessPair(const Instruction *I1, const Instruction *I2,
172  const RC_FLAG flags) :
173  I1(I1), I2(I2), flags(flags)
174  {
175  }
176 
178 
179  inline bool isFlaged(const RC_FLAG flag) const
180  {
181  return flags & flag;
182  }
183  inline const Instruction *getInstruction1() const
184  {
185  return I1;
186  }
187  inline const Instruction *getInstruction2() const
188  {
189  return I2;
190  }
192 
193  private:
194  const Instruction *I1;
195  const Instruction *I2;
196  RC_FLAG flags;
197  };
198 
201  {
202  release();
203  }
204 
206  void init(SVFModule* M)
207  {
208  this->M = M;
209  selectedValidationScenarios = RC_MHP | RC_ALIASES | RC_PROTECTED | RC_RACE;
210  collectValidationTargets();
211  }
212 
214  void analyze()
215  {
216  validateAll();
217  }
218 
220  void release()
221  {
222  }
223 
225  inline bool hasValidationTarget() const
226  {
227  return !accessPairs.empty();
228  }
229 
230 protected:
233 
234  virtual bool mayAccessAliases(const Instruction *I1,
235  const Instruction *I2)
236  {
237  selectedValidationScenarios &= ~RC_ALIASES;
238  return true;
239  }
240  virtual bool mayHappenInParallel(const Instruction *I1,
241  const Instruction *I2)
242  {
243  selectedValidationScenarios &= ~RC_MHP;
244  return true;
245  }
246  virtual bool protectedByCommonLocks(const Instruction *I1,
247  const Instruction *I2)
248  {
249  selectedValidationScenarios &= ~RC_PROTECTED;
250  return true;
251  }
252  virtual bool mayHaveDataRace(const Instruction *I1,
253  const Instruction *I2)
254  {
255  selectedValidationScenarios &= ~RC_RACE;
256  return true;
257  }
259 
266  {
267  // Collect call sites of all RC_ACCESS function calls.
268  std::vector<const CallInst*> csInsts;
269  const Function *F = M.getFunction(RC_ACCESS);
270  if (!F) return;
271 
272  for (Value::const_use_iterator it = F->use_begin(), ie =
273  F->use_end(); it != ie; ++it)
274  {
275  const Use *u = &*it;
276  const Value *user = u->getUser();
277  const CallInst *csInst = SVFUtil::dyn_cast<CallInst>(user);
278  assert(csInst);
279  csInsts.push_back(csInst);
280  }
281  assert(csInsts.size() % 2 == 0 && "We should have RC_ACCESS called in pairs.");
282 
283  // Sort the validation sites according to their ids.
284  std::sort(csInsts.begin(), csInsts.end(), compare);
285 
286  // Generate access pairs.
287  for (int i = 0, e = csInsts.size(); i != e;)
288  {
289  const CallInst *CI1 = csInsts[i++];
290  const CallInst *CI2 = csInsts[i++];
291  const ConstantInt *C = SVFUtil::dyn_cast<ConstantInt>(CI1->getOperand(1));
292  assert(C);
293  const Instruction *I1 = getPreviousMemoryAccessInst(CI1);
294  const Instruction *I2 = getPreviousMemoryAccessInst(CI2);
295  assert(I1 && I2 && "RC_ACCESS should be placed immediately after the target memory access.");
296  RC_FLAG flags = C->getZExtValue();
297  accessPairs.push_back(AccessPair(I1, I2, flags));
298  }
299  }
300 
302  void validateAll()
303  {
304  SVFUtil::outs() << SVFUtil::pasMsg(" --- Analysis Result Validation ---\n");
305 
306  // Iterate every memory access pair to perform the validation.
307  for (int i = 0, e = accessPairs.size(); i != e; ++i)
308  {
309  const AccessPair &ap = accessPairs[i];
310  const Instruction *I1 = ap.getInstruction1();
311  const Instruction *I2 = ap.getInstruction2();
312 
313  bool mhp = mayHappenInParallel(I1, I2);
314  bool alias = mayAccessAliases(I1, I2);
315  bool protect = protectedByCommonLocks(I1, I2);
316  bool racy = mayHaveDataRace(I1, I2);
317 
318  SVFUtil::outs() << "For the memory access pair at ("
319  << SVFUtil::getSourceLoc(I1) << ", "
320  << SVFUtil::getSourceLoc(I2) << ")\n";
321  if (selectedValidationScenarios & RC_ALIASES)
322  {
323  SVFUtil::outs() << "\t"
324  << getOutput("ALIASES", alias, ap.isFlaged(RC_ALIASES))
325  << "\n";
326  }
327  if (selectedValidationScenarios & RC_MHP)
328  {
329  SVFUtil::outs() << "\t"
330  << getOutput("MHP", mhp, ap.isFlaged(RC_MHP)) << "\n";
331  }
332  if (selectedValidationScenarios & RC_PROTECTED)
333  {
334  SVFUtil::outs() << "\t"
335  << getOutput("PROTECT", protect,
336  ap.isFlaged(RC_PROTECTED)) << "\n";
337  }
338  if (selectedValidationScenarios & RC_RACE)
339  {
340  SVFUtil::outs() << "\t"
341  << getOutput("RACE", racy, ap.isFlaged(RC_RACE))
342  << "\n";
343  }
344  }
345 
346  SVFUtil::outs() << "\n";
347  }
348 
350  inline std::string getOutput(const char *scenario,
351  bool analysisRes, bool expectedRes)
352  {
353  std::string ret(scenario);
354  ret += "\t";
355  if (expectedRes)
356  ret += " T: ";
357  else
358  ret += " F: ";
359  if (analysisRes == expectedRes)
360  ret += SVFUtil::sucMsg("SUCCESS");
361  else
362  ret += SVFUtil::errMsg("FAILURE");
363  return ret;
364  }
365 
366 private:
367  SVFModule* M;
368  std::vector<AccessPair> accessPairs;
370 
375  static bool compare(const CallInst *CI1, const CallInst *CI2)
376  {
377  const Value *V1 = CI1->getOperand(0);
378  const Value *V2 = CI2->getOperand(0);
379  const ConstantInt *C1 = SVFUtil::dyn_cast<ConstantInt>(V1);
380  const ConstantInt *C2 = SVFUtil::dyn_cast<ConstantInt>(V2);
381  assert(0 != C1 && 0 != C2);
382  return C1->getZExtValue() < C2->getZExtValue();
383  }
384 
391  const Instruction *I)
392  {
393  I = I->getPrevNode();
394  while (I)
395  {
396  if (SVFUtil::isa<LoadInst>(I) || SVFUtil::isa<StoreInst>(I))
397  return I;
398  if (const Function *callee = SVFUtil::getCallee(I))
399  {
400  if (ExtAPI::EFT_L_A0__A0R_A1R == ExtAPI::getExtAPI()->get_type(callee)
401  || callee->getName().find("llvm.memset") != StringRef::npos)
402  return I;
403  }
404  I = I->getPrevNode();
405  }
406  return nullptr;
407  }
408 
410 
411  static const RC_FLAG RC_MHP = 0x01;
412  static const RC_FLAG RC_ALIASES = 0x02;
413  static const RC_FLAG RC_PROTECTED = 0x04;
414  static const RC_FLAG RC_RACE = 0x10;
416 
419  static constexpr char const *RC_ACCESS = "RC_ACCESS";
420 };
421 
422 #endif /* MTARESULTVALIDATOR_H_ */
virtual bool protectedByCommonLocks(const Instruction *I1, const Instruction *I2)
llvm::Use Use
Definition: BasicTypes.h:87
std::string getOutputforInterlevAnalysis(const char *scenario, INTERLEV_FLAG analysisRes)
AccessPair(const Instruction *I1, const Instruction *I2, const RC_FLAG flags)
Constructor.
static constexpr char const * INTERLEV_ACCESS
static const INTERLEV_FLAG INTERLEV_UNSOUND
u32_t NodeID
Definition: SVFBasicTypes.h:80
std::string pasMsg(std::string msg)
Print each pass/phase message by converting a string into blue string output.
Definition: SVFUtil.cpp:99
static bool compare(const CallInst *CI1, const CallInst *CI2)
#define assert(ex)
Definition: util.h:141
void release()
Release resource.
MHP::InstToThreadStmtSetMap instToTSMap
llvm::CallInst CallInst
Definition: BasicTypes.h:143
static constexpr char const * CXT_THREAD
Map a statement to its thread interleavings.
virtual bool mayAccessAliases(const Instruction *I1, const Instruction *I2)
std::string getSourceLoc(const Value *val)
Return source code including line number and file name from debug information.
Definition: SVFUtil.cpp:259
Map< NodeID, Set< NodeID > > rthdToChildren
const Instruction * getPreviousMemoryAccessInst(const Instruction *I)
llvm::ConstantInt ConstantInt
Definition: BasicTypes.h:153
std::string sucMsg(std::string msg)
Returns successful message by converting a string into green string output.
Definition: SVFUtil.cpp:54
const Instruction * getInstruction1() const
MHP::ThreadStmtToThreadInterleav threadStmtToInterLeaving
std::string getOutput(const char *scenario, bool analysisRes, bool expectedRes)
Get the validation result string of a single validation scenario.
INTERLEV_FLAG validateInterleaving()
Validate the result of concurrent analysis.
virtual ~RaceResultValidator()
Destructor.
Map< NodeID, NodeID > vthdTorthd
std::string getOutput(const char *scenario, bool analysisRes)
llvm::Function Function
Definition: BasicTypes.h:76
Map< NodeID, NodeID > rthdTovthd
NodeID getIntArg(const Instruction *inst, unsigned int arg_num)
llvm::Instruction Instruction
Definition: BasicTypes.h:79
const Instruction * getInstruction2() const
virtual bool mayHaveDataRace(const Instruction *I1, const Instruction *I2)
Map< NodeID, CallStrCxt > vthdToCxt
SmallVector16 CallStrCxt
std::vector< std::string > getStringArg(const Instruction *inst, unsigned int arg_num)
const SVFFunction * getCallee(const CallSite cs)
Return callee of a callsite. Return null if this is an indirect call.
Definition: SVFUtil.h:221
bool hasValidationTarget() const
Check if the input program has validation target.
void validateAll()
Perform validation for all targets.
raw_ostream & outs()
Overwrite llvm::outs()
Definition: SVFUtil.h:47
const Instruction * getPreviousMemoryAccessInst(const Instruction *I)
virtual bool mayHappenInParallel(const Instruction *I1, const Instruction *I2)
llvm::SparseBitVector NodeBS
Definition: SVFBasicTypes.h:87
static const INTERLEV_FLAG INTERLEV_IMPRECISE
static const INTERLEV_FLAG INTERLEV_TRUE
Constant INTERLEV_FLAG values.
std::vector< std::string > & split(const std::string &s, char delim, std::vector< std::string > &elems)
bool isFlaged(const RC_FLAG flag) const
Class member access.
ThreadCallGraph * tcg
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
Definition: Casting.h:343
CallStrCxt getCxtArg(const Instruction *inst, unsigned int arg_num)
void dumpCxt(const CallStrCxt &cxt) const
void analyze()
Analysis.
void dumpInterlev(NodeBS &lev)
std::vector< AccessPair > accessPairs
bool matchCxt(const CallStrCxt cxt1, const CallStrCxt cxt2) const
std::string errMsg(std::string msg)
Print error message by converting a string into red string output.
Definition: SVFUtil.cpp:76
llvm::Value Value
Definition: BasicTypes.h:78
static constexpr char const * TCT_ACCESS
Map< NodeID, const CallInst * > csnumToInstMap
void init(SVFModule *M)
Initialization.