Static Value-Flow Analysis
Loading...
Searching...
No Matches
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
38using namespace SVF;
39using namespace SVFUtil;
40using 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> }}
47void SVFG::writeToFile(const string& filename)
48{
49 outs() << "Writing SVFG analysis to '" << filename << "'...";
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";
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 {
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;
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 {
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;
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
207void 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
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
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 }
281 if(!MR.empty())
282 {
284 }
285 else
286 {
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);
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
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)
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));
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));
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 {
420 tempMRVer = getMRVERFromString(attribute);
421 addIntraIndirectVFEdge(dst,src, tempMRVer->getMR()->getPointsTo());
422 }
423 else
424 {
425 }
426 }
429}
430
432{
433 if(s == "")
434 {
435 return NULL;
436 }
437 string temp;
438 size_t last = 0;
439 size_t next = 0;
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
449 string point;
451 while (getline(ss, point, ' '))
452 {
454 NodeID obj;
455 sss >> obj;
456 dstPts.set(obj);
457 }
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;
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
475 NodeID obj2;
476 ss2 >> obj2;
477 // create mrver
479 return tempMRVer;
480}
#define F(f)
item next
Definition cJSON.cpp:2224
newitem type
Definition cJSON.cpp:2739
int index
Definition cJSON.h:170
iterator begin()
Iterators.
virtual const SVFBasicBlock * getBB() const
Return the basic block of this ICFGNode.
Definition ICFGNode.h:82
ICFGNode * getICFGNode(NodeID id) const
Get a ICFG node.
Definition ICFG.h:86
Memory Region class.
Definition MemRegion.h:56
Set< const CallICFGNode * > CallInstSet
NodeID getId() const
Get ID.
const ICFGNode * front() const
Definition SVFValue.h:605
void ATVFNodeStart()
Definition SVFGStat.h:139
void indVFEdgeEnd()
Definition SVFGStat.h:124
void ATVFNodeEnd()
Definition SVFGStat.h:144
void indVFEdgeStart()
Definition SVFGStat.h:119
ActualOUTSVFGNodeSet & getActualOUTSVFGNodes(const CallICFGNode *cs)
Definition SVFG.h:215
SVFGEdge * addInterIndirectVFCallEdge(const ActualINSVFGNode *src, const FormalINSVFGNode *dst, CallSiteID csId)
Add inter VF edge from callsite mu to function entry chi.
Definition SVFG.cpp:545
void connectFromGlobalToProgEntry()
Connect indirect SVFG edges from global initializers (store) to main function entry.
Definition SVFG.cpp:428
SVFGNode * getSVFGNode(NodeID id) const
Get a SVFG node.
Definition SVFG.h:150
void addIntraMSSAPHISVFGNode(ICFGNode *BlockICFGNode, const Map< u32_t, const MRVer * >::const_iterator opVerBegin, const Map< u32_t, const MRVer * >::const_iterator opVerEnd, const MRVer *resVer, const NodeID nodeId)
Add memory SSA PHI SVFG node.
Definition SVFG.h:437
ActualINSVFGNodeSet & getActualINSVFGNodes(const CallICFGNode *cs)
Get SVFGNode set.
Definition SVFG.h:210
void addActualOUTSVFGNode(const CallICFGNode *callsite, const MRVer *resVer, const NodeID nodeId)
Add memory callsite chi SVFG node.
Definition SVFG.h:428
virtual void writeToFile(const std::string &filename)
void addFormalOUTSVFGNode(const FunExitICFGNode *funExit, const MRVer *ver, const NodeID nodeId)
Add memory Function return mu SVFG node.
Definition SVFG.h:412
MemSSA::LOADMU LOADMU
Definition SVFG.h:92
MemSSA::CHISet CHISet
Definition SVFG.h:88
virtual MRVer * getMRVERFromString(const std::string &input)
void addActualINSVFGNode(const CallICFGNode *callsite, const MRVer *ver, const NodeID nodeId)
Add memory callsite mu SVFG node.
Definition SVFG.h:420
virtual void readFile(const std::string &filename)
std::unique_ptr< MemSSA > mssa
Definition SVFG.h:106
void addFormalINSVFGNode(const FunEntryICFGNode *funEntry, const MRVer *resVer, const NodeID nodeId)
Add memory Function entry chi SVFG node.
Definition SVFG.h:403
NodeID getDef(const PAGNode *pagNode) const
Definition SVFG.h:356
SVFGEdge * addInterIndirectVFRetEdge(const FormalOUTSVFGNode *src, const ActualOUTSVFGNode *dst, CallSiteID csId)
Add inter VF edge from function exit mu to callsite chi.
Definition SVFG.cpp:560
void setDef(const PAGNode *pagNode, const SVFGNode *node)
Given a PAGNode, set/get its def SVFG node (definition of top level pointers)
Definition SVFG.h:352
MemSSA::MUSet MUSet
Definition SVFG.h:87
SVFGEdge * addIntraIndirectVFEdge(NodeID srcId, NodeID dstId, const NodeBS &cpts)
Add indirect def-use edges of a memory region between two statements,.
Definition SVFG.cpp:463
MemSSA::STORECHI STORECHI
Definition SVFG.h:93
SVFGStat * stat
Definition SVFG.h:105
ICFG * getICFG() const
Definition SVFIR.h:172
SVFStmtSetTy PAGEdgeSetTy
virtual SVFStmt::SVFStmtSetTy & getPAGEdgeSet(SVFStmt::PEDGEK kind)
Get PAGEdge set.
Definition VFG.h:436
VFGNodeIDToNodeMapTy::iterator iterator
Definition VFG.h:80
SVFIR * pag
Definition VFG.h:104
CallSiteID getCallSiteID(const CallICFGNode *cs, const SVFFunction *func) const
Get callsite given a callsiteID.
Definition VFG.h:178
StmtVFGNode * getStmtVFGNode(const PAGEdge *pagEdge) const
Get an VFGNode.
Definition VFG.h:199
NodeID totalVFGNode
Definition VFG.h:88
#define NULL
Definition extapi.c:2
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
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:74