Static Value-Flow Analysis
SVFGReadWrite.cpp
Go to the documentation of this file.
1 //===- SVFGReadWrite.cpp -- SVFG read & write-----------------------------------//
2 //
3 // SVF: Static Value-Flow Analysis
4 //
5 // Copyright (C) <2013-2017> <Yulei Sui>
6 //
7 
8 // This program is free software: you can redistribute it and/or modify
9 // it under the terms of the GNU Affero General Public License as published by
10 // the Free Software Foundation, either version 3 of the License, or
11 // (at your option) any later version.
12 
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU Affero General Public License for more details.
17 
18 // You should have received a copy of the GNU Affero General Public License
19 // along with this program. If not, see <http://www.gnu.org/licenses/>.
20 //
21 //===----------------------------------------------------------------------===//
22 
23 /*
24  * SVFGReadWrite.cpp
25  *
26  * Created on: May 21, 2022
27  * Author: Jeffrey Ma
28  */
29 
30 #include "SVFIR/SVFModule.h"
31 #include "Util/SVFUtil.h"
32 #include "Graphs/SVFG.h"
33 #include "Graphs/SVFGStat.h"
35 #include <fstream>
36 #include "Util/Options.h"
37 
38 using namespace SVF;
39 using namespace SVFUtil;
40 using namespace std;
41 
42 // Format of file
43 // __Nodes__
44 // SVFGNodeID: <id> >= <node type> >= MVER: {MRVERID: <id> MemRegion: pts{<pts> } MRVERSION: <version> MSSADef: <version>, pts{<pts> }} >= ICFGNodeID: <id>
45 // __Edges__
46 // srcSVFGNodeID: <id> => dstSVFGNodeID: <id> >= <edge type> | MVER: {MRVERID: <id> MemRegion: pts{<pts> } MRVERSION: <version> MSSADef: <version>, pts{<pts> }}
47 void SVFG::writeToFile(const string& filename)
48 {
49  outs() << "Writing SVFG analysis to '" << filename << "'...";
50  error_code err;
51  std::fstream f(filename.c_str(), std::ios_base::out);
52  if (!f.good())
53  {
54  outs() << " error opening file for writing!\n";
55  return;
56  }
57  f << "__Nodes__\n";
58  // Iterate over nodes and write to file
59  for(iterator it = begin(), eit = end(); it!=eit; ++it)
60  {
61  NodeID nodeId = it->first;
62  const SVFGNode* node = it->second;
63  if(const FormalINSVFGNode* formalIn = SVFUtil::dyn_cast<FormalINSVFGNode>(node))
64  {
65  //node
66  f << "SVFGNodeID: " << nodeId << " >= " << "FormalINSVFGNode";
67  f << " >= MVER: {";
68  f << *formalIn->getMRVer() << "} >= ICFGNodeID: " << formalIn->getFunEntryNode()->getId() << "\n";
69  }
70  else if(const FormalOUTSVFGNode* formalOut = SVFUtil::dyn_cast<FormalOUTSVFGNode>(node))
71  {
72  //node
73  f << "SVFGNodeID: " << nodeId << " >= " << "FormalOUTSVFGNode";
74  f << " >= MVER: {";
75  f << *formalOut->getMRVer() << "} >= ICFGNodeID: " << formalOut->getFunExitNode()->getId() << "\n";
76  }
77  else if(const ActualINSVFGNode* actualIn = SVFUtil::dyn_cast<ActualINSVFGNode>(node))
78  {
79  //node
80  f << "SVFGNodeID: " << nodeId << " >= " << "ActualINSVFGNode";
81  f << " >= MVER: {";
82  f << *actualIn->getMRVer() << "} >= ICFGNodeID: " << actualIn->getCallSite()->getId() << "\n";
83  }
84  else if(const ActualOUTSVFGNode* actualOut = SVFUtil::dyn_cast<ActualOUTSVFGNode>(node))
85  {
86  //node
87  f << "SVFGNodeID: " << nodeId << " >= " << "ActualOUTSVFGNode" << " >= MVER: {";
88  f << *actualOut->getMRVer() << "} >= ICFGNodeID: " << actualOut->getCallSite()->getId() << "\n";
89  }
90  else if(const MSSAPHISVFGNode* phiNode = SVFUtil::dyn_cast<MSSAPHISVFGNode>(node))
91  {
92  //node
93  f << "SVFGNodeID: " << nodeId << " >= " << "PHISVFGNode";
94  unordered_map<u32_t,const MRVer*> opvers;
95  for (MemSSA::PHI::OPVers::const_iterator it = phiNode->opVerBegin(), eit = phiNode->opVerEnd();
96  it != eit; it++)
97  {
98  opvers.insert(make_pair(it->first, it->second));
99  }
100  // opvers
101  f << " >= MVER: {";
102  f << *phiNode->getResVer();
103  const ICFGNode* inst = phiNode->getICFGNode()->getBB()->front();
104  f << "} >= ICFGNodeID: " << inst->getId();
105  f << " >= OPVers: {";
106  for (auto x: opvers)
107  {
108  const MRVer* op = x.second;
109  f << "{" << *op << "}" << ",";
110  }
111  f << "}\n";
112  }
113  }
114 
115  f << "\n\n__Edges__\n";
116  // Iterate over edges and write to file
117  for(iterator it = begin(), eit = end(); it!=eit; ++it)
118  {
119  NodeID nodeId = it->first;
120  const SVFGNode* node = it->second;
121  if(const LoadSVFGNode* loadNode = SVFUtil::dyn_cast<LoadSVFGNode>(node))
122  {
123  MUSet& muSet = mssa->getMUSet(SVFUtil::cast<LoadStmt>(loadNode->getPAGEdge()));
124  for(MUSet::iterator it = muSet.begin(), eit = muSet.end(); it!=eit; ++it)
125  {
126  if(LOADMU* mu = SVFUtil::dyn_cast<LOADMU>(*it))
127  {
128  NodeID def = getDef(mu->getMRVer());
129  f << "srcSVFGNodeID: " << nodeId << " => " << "dstSVFGNodeID: " << def << " >= LoadNode | MVER: {" << *mu->getMRVer() << "}" << "\n";
130  }
131  }
132  }
133  else if(const StoreSVFGNode* storeNode = SVFUtil::dyn_cast<StoreSVFGNode>(node))
134  {
135  CHISet& chiSet = mssa->getCHISet(SVFUtil::cast<StoreStmt>(storeNode->getPAGEdge()));
136  for(CHISet::iterator it = chiSet.begin(), eit = chiSet.end(); it!=eit; ++it)
137  {
138  if(STORECHI* chi = SVFUtil::dyn_cast<STORECHI>(*it))
139  {
140  NodeID def = getDef(chi->getOpVer());
141  f << "srcSVFGNodeID: " << nodeId << " => " << "dstSVFGNodeID: " << def << " >= StoreNode | MVER: {" << *chi->getOpVer() << "}" << "\n";
142  }
143  }
144  }
145  else if(const FormalINSVFGNode* formalIn = SVFUtil::dyn_cast<FormalINSVFGNode>(node))
146  {
147  PTACallGraphEdge::CallInstSet callInstSet;
148  mssa->getPTA()->getCallGraph()->getDirCallSitesInvokingCallee(formalIn->getFun(),callInstSet);
149  for(PTACallGraphEdge::CallInstSet::iterator it = callInstSet.begin(), eit = callInstSet.end(); it!=eit; ++it)
150  {
151  const CallICFGNode* cs = *it;
152  if(!mssa->hasMU(cs))
153  continue;
154  ActualINSVFGNodeSet& actualIns = getActualINSVFGNodes(cs);
155  for(ActualINSVFGNodeSet::iterator ait = actualIns.begin(), aeit = actualIns.end(); ait!=aeit; ++ait)
156  {
157  const ActualINSVFGNode* actualIn = SVFUtil::cast<ActualINSVFGNode>(getSVFGNode(*ait));
158  f << "srcSVFGNodeID: " << nodeId << " => " << "dstSVFGNodeID: " << actualIn->getId() << " >= FormalINSVFGNode" << "\n";
159  }
160  }
161  }
162  else if(const FormalOUTSVFGNode* formalOut = SVFUtil::dyn_cast<FormalOUTSVFGNode>(node))
163  {
164  PTACallGraphEdge::CallInstSet callInstSet;
165  mssa->getPTA()->getCallGraph()->getDirCallSitesInvokingCallee(formalOut->getFun(),callInstSet);
166  for(PTACallGraphEdge::CallInstSet::iterator it = callInstSet.begin(), eit = callInstSet.end(); it!=eit; ++it)
167  {
168  const CallICFGNode* cs = *it;
169  if(!mssa->hasCHI(cs))
170  continue;
171  ActualOUTSVFGNodeSet& actualOuts = getActualOUTSVFGNodes(cs);
172  for(ActualOUTSVFGNodeSet::iterator ait = actualOuts.begin(), aeit = actualOuts.end(); ait!=aeit; ++ait)
173  {
174  const ActualOUTSVFGNode* actualOut = SVFUtil::cast<ActualOUTSVFGNode>(getSVFGNode(*ait));
175  f << "srcSVFGNodeID: " << nodeId << " => " << "dstSVFGNodeID: " << actualOut->getId() << " >= FormalOUTSVFGNode" << "\n";
176  }
177  }
178  NodeID def = getDef(formalOut->getMRVer());
179  f << "srcSVFGNodeID: " << nodeId << " => " << "dstSVFGNodeID: " << def << " >= FormalOUTSVFGNode | intra" << "\n";
180  }
181  else if(const ActualINSVFGNode* actualIn = SVFUtil::dyn_cast<ActualINSVFGNode>(node))
182  {
183  NodeID def = getDef(actualIn->getMRVer());
184  f << "srcSVFGNodeID: " << nodeId << " => " << "dstSVFGNodeID: " << def << " >= ActualINSVFGNode" << "\n";
185 
186  }
187  else if(const MSSAPHISVFGNode* phiNode = SVFUtil::dyn_cast<MSSAPHISVFGNode>(node))
188  {
189  for (MemSSA::PHI::OPVers::const_iterator it = phiNode->opVerBegin(), eit = phiNode->opVerEnd();
190  it != eit; it++)
191  {
192  const MRVer* op = it->second;
193  NodeID def = getDef(op);
194  f << "srcSVFGNodeID: " << nodeId << " => " << "dstSVFGNodeID: " << def << " >= PHISVFGNode | MVER: {" << *op << "}" << "\n";
195  }
196  }
197  }
198  // Job finish and close file
199  f.close();
200  if (f.good())
201  {
202  outs() << "\n";
203  return;
204  }
205 }
206 
207 void SVFG::readFile(const string& filename)
208 {
209  outs() << "Loading SVFG analysis results from '" << filename << "'...";
210  ifstream F(filename.c_str());
211  if (!F.is_open())
212  {
213  outs() << " error opening file for reading!\n";
214  return;
215  }
216 
217  PAGEdge::PAGEdgeSetTy& stores = getPAGEdgeSet(PAGEdge::Store);
218  for (PAGEdge::PAGEdgeSetTy::iterator iter = stores.begin(), eiter =
219  stores.end(); iter != eiter; ++iter)
220  {
221  StoreStmt* store = SVFUtil::cast<StoreStmt>(*iter);
222  const StmtSVFGNode* sNode = getStmtVFGNode(store);
223  for(CHISet::iterator pi = mssa->getCHISet(store).begin(), epi = mssa->getCHISet(store).end(); pi!=epi; ++pi)
224  setDef((*pi)->getResVer(),sNode);
225  }
226  //outer loop through each line in the file
227  string line;
228  // add nodes
229  stat->ATVFNodeStart();
230  while (F.good())
231  {
232  getline(F, line);
233  if (line.empty())
234  continue;
235  if (line.find("__Edges__") != std::string::npos)
236  break;
237 
238  std::string s = line;
239  std::string delimiter = " >= ";
240  string temp;
241  int index = 0;
242  //implement delimiter to split string using ">="
243  size_t next = 0;
244  size_t last = 0;
245  size_t outer_last = 0;
246  size_t nextTemp; //size_t lastTemp;
247  NodeID id = 0;
248  string type;
249  string MR;
250  string basicBlock;
251  string opVer;
252  //inner loop through to get each element in the line
253  while ((next = s.find(delimiter, last)) != string::npos)
254  {
255  temp = s.substr(last, next-last);
256  last = next + 4;
257  outer_last = next + 4;
258  if(index == 0)
259  {
260  nextTemp = temp.find("SVFGNodeID: ") + 12;
261  id = atoi(temp.substr(nextTemp).c_str());
262  }
263  if(index == 1)
264  {
265  type = temp;
266  }
267  if(index > 1)
268  {
269  if(index == 2)
270  {
271  MR = temp;
272  }
273  if(index == 3)
274  {
275  basicBlock = temp;
276  }
277  }
278  index++;
279  }
280  MRVer* tempMRVer;
281  if(!MR.empty())
282  {
283  tempMRVer = getMRVERFromString(MR);
284  }
285  else
286  {
287  tempMRVer = getMRVERFromString("");
288  }
289  //add nodes using the variables we extracted
290  if(type == "FormalINSVFGNode")
291  {
292  outer_last = s.find("ICFGNodeID: ") + 12;
293  NodeID FunID = atoi(s.substr(outer_last).c_str());
294  addFormalINSVFGNode(SVFUtil::dyn_cast<FunEntryICFGNode>(pag->getICFG()->getICFGNode(FunID)), tempMRVer, id);
295  }
296  else if(type == "FormalOUTSVFGNode")
297  {
298  outer_last = s.find("ICFGNodeID: ") + 12;
299  NodeID FunID = atoi(s.substr(outer_last).c_str());
300  addFormalOUTSVFGNode(SVFUtil::dyn_cast<FunExitICFGNode>(pag->getICFG()->getICFGNode(FunID)), tempMRVer, id);
301  }
302  else if(type == "ActualINSVFGNode")
303  {
304  outer_last = s.find("ICFGNodeID: ") + 12;
305  NodeID CallSiteID = atoi(s.substr(outer_last).c_str());
306  addActualINSVFGNode(SVFUtil::dyn_cast<CallICFGNode>(pag->getICFG()->getICFGNode(CallSiteID)), tempMRVer, id);
307  }
308  else if(type == "ActualOUTSVFGNode")
309  {
310  outer_last = s.find("ICFGNodeID: ") + 12;
311  NodeID CallSiteID = atoi(s.substr(outer_last).c_str());
312  addActualOUTSVFGNode(SVFUtil::dyn_cast<CallICFGNode>(pag->getICFG()->getICFGNode(CallSiteID)), tempMRVer, id);
313  }
314  else if (type == "PHISVFGNode")
315  {
316  opVer = s.substr(outer_last);
317  next = opVer.find("{") + 1;
318  last = opVer.find(",}");
319  temp = opVer.substr(next, last);
321  int index = 0;
322  while ((next = temp.find("{") + 1) != string::npos)
323  {
324  if (temp == ",}")
325  break;
326  last = temp.find("},");
327  string temp1;
328  temp1 = temp.substr(next, last-next);
329  MRVer* tempOPVer = getMRVERFromString(temp1);
330  OPVers.insert(make_pair(index, tempOPVer));
331  temp = temp.substr(last + 1);
332  index++;
333  }
334  next = basicBlock.find("ICFGNodeID: ") + 12;
335  temp = basicBlock.substr(next);
336  addIntraMSSAPHISVFGNode(pag->getICFG()->getICFGNode(atoi(temp.c_str())), OPVers.begin(), OPVers.end(), tempMRVer, id);
337  }
338  else
339  {
340  }
341 
342  if (totalVFGNode < id)
343  totalVFGNode = id + 1;
344  }
345  stat->ATVFNodeEnd();
346 
347  stat->indVFEdgeStart();
348  // Edges
349  while (F.good())
350  {
351  getline(F, line);
352  if (line.empty())
353  continue;
354 
355  std::string s = line;
356  std::string delimiter = " >= ";
357  string temp;
358  // int index = 0;
359  size_t last = 0;
360  size_t next = 0; // size_t outer_last = 0;
361  string edge;
362  string attributes;
363 
364  next = s.find(delimiter);
365 
366  edge = s.substr(0, next);
367  attributes = s.substr(next + 4);
368 
369  // extract nodeIDs for src and dst nodes
370  NodeID src;
371  NodeID dst;
372  next = edge.find("srcSVFGNodeID: ") + 15;
373  last = edge.find(" => ");
374  src = atoi(edge.substr(next, last-next).c_str());
375  next = edge.find("dstSVFGNodeID: ") + 15;
376  dst = atoi(edge.substr(next).c_str());
377 
378  string type;
379  string attribute;
380  if (attributes.find(" | ") == string::npos)
381  type = attributes;
382  else
383  {
384  next = attributes.find(" | ");
385  type = attributes.substr(0, next);
386  attribute = attributes.substr(next + 3);
387  }
388 
389  if(type == "FormalINSVFGNode")
390  {
391  const FormalINSVFGNode* formalIn = SVFUtil::cast<FormalINSVFGNode>(getSVFGNode(src));
392  const ActualINSVFGNode* actualIn = SVFUtil::cast<ActualINSVFGNode>(getSVFGNode(dst));
393  addInterIndirectVFCallEdge(actualIn,formalIn, getCallSiteID(actualIn->getCallSite(), formalIn->getFun()));
394  }
395  else if(type == "FormalOUTSVFGNode")
396  {
397  const FormalOUTSVFGNode* formalOut = SVFUtil::cast<FormalOUTSVFGNode>(getSVFGNode(src));
398  if (attribute.find("intra") != string::npos)
399  {
400  addIntraIndirectVFEdge(dst, src, formalOut->getMRVer()->getMR()->getPointsTo());
401  }
402  else
403  {
404  const ActualOUTSVFGNode* actualOut = SVFUtil::cast<ActualOUTSVFGNode>(getSVFGNode(dst));
405  addInterIndirectVFRetEdge(formalOut,actualOut,getCallSiteID(actualOut->getCallSite(), formalOut->getFun()));
406  }
407  }
408  else if(type == "ActualINSVFGNode")
409  {
410  const ActualINSVFGNode* actualIn = SVFUtil::cast<ActualINSVFGNode>(getSVFGNode(src));
411  addIntraIndirectVFEdge(dst,src, actualIn->getMRVer()->getMR()->getPointsTo());
412  }
413  else if(type == "ActualOUTSVFGNode")
414  {
415  // There's no need to connect actual out node to its definition site in the same function.
416  }
417  else if (type == "StoreNode" || type == "LoadNode" || type == "PHISVFGNode")
418  {
419  MRVer* tempMRVer;
420  tempMRVer = getMRVERFromString(attribute);
421  addIntraIndirectVFEdge(dst,src, tempMRVer->getMR()->getPointsTo());
422  }
423  else
424  {
425  }
426  }
427  stat->indVFEdgeEnd();
428  connectFromGlobalToProgEntry();
429 }
430 
432 {
433  if(s == "")
434  {
435  return NULL;
436  }
437  string temp;
438  size_t last = 0;
439  size_t next = 0;
440  MRVer* tempMRVer;
441  MemRegion* tempMemRegion;
442  MSSADEF* tempDef;
443  //{create Memory Region object
444  next = s.find("MemRegion: pts{") + 15;
445  last = s.find("} MRVERSION: ");
446  temp = s.substr(next, last-next);
447  // convert string to PointsTo
448  NodeBS dstPts;
449  string point;
450  stringstream ss(temp);
451  while (getline(ss, point, ' '))
452  {
453  istringstream sss(point);
454  NodeID obj;
455  sss >> obj;
456  dstPts.set(obj);
457  }
458  tempMemRegion = new MemRegion(dstPts);
459  // create mssdef
460  next = s.find("MSSADef: ") + 9;
461  last = s.find("} >=");
462  temp = s.substr(next, last-next);
463  // convert string to deftype
464  istringstream ss1(temp.substr(0, temp.find(", ")));
465  int obj1;
466  ss1 >> obj1;
467  MSSADEF::DEFTYPE defType = static_cast<MSSADEF::DEFTYPE>(obj1);
468  tempDef = new MSSADEF(defType, tempMemRegion);
469  // mrversion
470  next = s.find("MRVERSION: ") + 11;
471  last = s.find(" MSSADef:");
472  temp = s.substr(next, last-next);
473  // convert mrversion to nodeid
474  istringstream ss2(temp);
475  NodeID obj2;
476  ss2 >> obj2;
477  // create mrver
478  tempMRVer = new MRVer(tempMemRegion, obj2, tempDef);
479  return tempMRVer;
480 }
#define F(f)
return NULL
Definition: cJSON.cpp:1173
item next
Definition: cJSON.cpp:2224
newitem type
Definition: cJSON.cpp:2739
int index
Definition: cJSON.h:170
const char *const string
Definition: cJSON.h:172
const MRVer * getMRVer() const
Ver.
Definition: SVFGNode.h:188
const CallICFGNode * getCallSite() const
Callsite.
Definition: SVFGNode.h:182
const CallICFGNode * getCallSite() const
Callsite.
Definition: SVFGNode.h:232
const MRVer * getMRVer() const
Definition: SVFGNode.h:141
IDToNodeMapTy::iterator iterator
Node Iterators.
Definition: GenericGraph.h:606
virtual const SVFBasicBlock * getBB() const
Return the basic block of this ICFGNode.
Definition: ICFGNode.h:82
const MemRegion * getMR() const
Return the memory region.
Definition: MSSAMuChi.h:63
Memory Region class.
Definition: MemRegion.h:56
const NodeBS & getPointsTo() const
Return points-to.
Definition: MemRegion.h:83
Set< const CallICFGNode * > CallInstSet
Definition: PTACallGraph.h:55
NodeID getId() const
Get ID.
Definition: GenericGraph.h:260
const ICFGNode * front() const
Definition: SVFValue.h:594
virtual void writeToFile(const std::string &filename)
MemSSA::CHISet CHISet
Definition: SVFG.h:88
virtual MRVer * getMRVERFromString(const std::string &input)
virtual void readFile(const std::string &filename)
MemSSA::MUSet MUSet
Definition: SVFG.h:87
SVFStmtSetTy PAGEdgeSetTy
iterator end() const
void set(unsigned Idx)
iterator begin() const
virtual const SVFFunction * getFun() const
Get the function of this SVFGNode.
Definition: VFGNode.h:79
std::ostream & outs()
Overwrite llvm::outs()
Definition: SVFUtil.h:50
for isBitcode
Definition: BasicTypes.h:68
unsigned CallSiteID
Definition: GeneralType.h:58
u32_t NodeID
Definition: GeneralType.h:55
std::unordered_map< Key, Value, Hash, KeyEqual, Allocator > Map
Definition: GeneralType.h:101