Static Value-Flow Analysis
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
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 "Util/SVFUtil.h"
31#include "Graphs/SVFG.h"
32#include "Graphs/SVFGStat.h"
34#include <fstream>
35#include "Util/Options.h"
36
37using namespace SVF;
38using namespace SVFUtil;
39using namespace std;
40
41// Format of file
42// __Nodes__
43// SVFGNodeID: <id> >= <node type> >= MVER: {MRVERID: <id> MemRegion: pts{<pts> } MRVERSION: <version> MSSADef: <version>, pts{<pts> }} >= ICFGNodeID: <id>
44// __Edges__
45// srcSVFGNodeID: <id> => dstSVFGNodeID: <id> >= <edge type> | MVER: {MRVERID: <id> MemRegion: pts{<pts> } MRVERSION: <version> MSSADef: <version>, pts{<pts> }}
46void SVFG::writeToFile(const string& filename)
47{
48 outs() << "Writing SVFG analysis to '" << filename << "'...";
50 std::fstream f(filename.c_str(), std::ios_base::out);
51 if (!f.good())
52 {
53 outs() << " error opening file for writing!\n";
54 return;
55 }
56 f << "__Nodes__\n";
57 // Iterate over nodes and write to file
58 for(iterator it = begin(), eit = end(); it!=eit; ++it)
59 {
60 NodeID nodeId = it->first;
61 const SVFGNode* node = it->second;
62 if(const FormalINSVFGNode* formalIn = SVFUtil::dyn_cast<FormalINSVFGNode>(node))
63 {
64 //node
65 f << "SVFGNodeID: " << nodeId << " >= " << "FormalINSVFGNode";
66 f << " >= MVER: {";
67 f << *formalIn->getMRVer() << "} >= ICFGNodeID: " << formalIn->getFunEntryNode()->getId() << "\n";
68 }
69 else if(const FormalOUTSVFGNode* formalOut = SVFUtil::dyn_cast<FormalOUTSVFGNode>(node))
70 {
71 //node
72 f << "SVFGNodeID: " << nodeId << " >= " << "FormalOUTSVFGNode";
73 f << " >= MVER: {";
74 f << *formalOut->getMRVer() << "} >= ICFGNodeID: " << formalOut->getFunExitNode()->getId() << "\n";
75 }
76 else if(const ActualINSVFGNode* actualIn = SVFUtil::dyn_cast<ActualINSVFGNode>(node))
77 {
78 //node
79 f << "SVFGNodeID: " << nodeId << " >= " << "ActualINSVFGNode";
80 f << " >= MVER: {";
81 f << *actualIn->getMRVer() << "} >= ICFGNodeID: " << actualIn->getCallSite()->getId() << "\n";
82 }
83 else if(const ActualOUTSVFGNode* actualOut = SVFUtil::dyn_cast<ActualOUTSVFGNode>(node))
84 {
85 //node
86 f << "SVFGNodeID: " << nodeId << " >= " << "ActualOUTSVFGNode" << " >= MVER: {";
87 f << *actualOut->getMRVer() << "} >= ICFGNodeID: " << actualOut->getCallSite()->getId() << "\n";
88 }
89 else if(const MSSAPHISVFGNode* phiNode = SVFUtil::dyn_cast<MSSAPHISVFGNode>(node))
90 {
91 //node
92 f << "SVFGNodeID: " << nodeId << " >= " << "PHISVFGNode";
94 for (MemSSA::PHI::OPVers::const_iterator it = phiNode->opVerBegin(), eit = phiNode->opVerEnd();
95 it != eit; it++)
96 {
97 opvers.insert(make_pair(it->first, it->second));
98 }
99 // opvers
100 f << " >= MVER: {";
101 f << *phiNode->getResVer();
102 const ICFGNode* inst = phiNode->getICFGNode()->getBB()->front();
103 f << "} >= ICFGNodeID: " << inst->getId();
104 f << " >= OPVers: {";
105 for (auto x: opvers)
106 {
107 const MRVer* op = x.second;
108 f << "{" << *op << "}" << ",";
109 }
110 f << "}\n";
111 }
112 }
113
114 f << "\n\n__Edges__\n";
115 // Iterate over edges and write to file
116 for(iterator it = begin(), eit = end(); it!=eit; ++it)
117 {
118 NodeID nodeId = it->first;
119 const SVFGNode* node = it->second;
120 if(const LoadSVFGNode* loadNode = SVFUtil::dyn_cast<LoadSVFGNode>(node))
121 {
122 MUSet& muSet = mssa->getMUSet(SVFUtil::cast<LoadStmt>(loadNode->getPAGEdge()));
123 for(MUSet::iterator it = muSet.begin(), eit = muSet.end(); it!=eit; ++it)
124 {
125 if(LOADMU* mu = SVFUtil::dyn_cast<LOADMU>(*it))
126 {
127 NodeID def = getDef(mu->getMRVer());
128 f << "srcSVFGNodeID: " << nodeId << " => " << "dstSVFGNodeID: " << def << " >= LoadNode | MVER: {" << *mu->getMRVer() << "}" << "\n";
129 }
130 }
131 }
132 else if(const StoreSVFGNode* storeNode = SVFUtil::dyn_cast<StoreSVFGNode>(node))
133 {
134 CHISet& chiSet = mssa->getCHISet(SVFUtil::cast<StoreStmt>(storeNode->getPAGEdge()));
135 for(CHISet::iterator it = chiSet.begin(), eit = chiSet.end(); it!=eit; ++it)
136 {
137 if(STORECHI* chi = SVFUtil::dyn_cast<STORECHI>(*it))
138 {
139 NodeID def = getDef(chi->getOpVer());
140 f << "srcSVFGNodeID: " << nodeId << " => " << "dstSVFGNodeID: " << def << " >= StoreNode | MVER: {" << *chi->getOpVer() << "}" << "\n";
141 }
142 }
143 }
144 else if(const FormalINSVFGNode* formalIn = SVFUtil::dyn_cast<FormalINSVFGNode>(node))
145 {
147 mssa->getPTA()->getCallGraph()->getDirCallSitesInvokingCallee(formalIn->getFun(),callInstSet);
148 for(CallGraphEdge::CallInstSet::iterator it = callInstSet.begin(), eit = callInstSet.end(); it!=eit; ++it)
149 {
150 const CallICFGNode* cs = *it;
151 if(!mssa->hasMU(cs))
152 continue;
155 {
156 const ActualINSVFGNode* actualIn = SVFUtil::cast<ActualINSVFGNode>(getSVFGNode(*ait));
157 f << "srcSVFGNodeID: " << nodeId << " => " << "dstSVFGNodeID: " << actualIn->getId() << " >= FormalINSVFGNode" << "\n";
158 }
159 }
160 }
161 else if(const FormalOUTSVFGNode* formalOut = SVFUtil::dyn_cast<FormalOUTSVFGNode>(node))
162 {
164 mssa->getPTA()->getCallGraph()->getDirCallSitesInvokingCallee(formalOut->getFun(),callInstSet);
165 for(CallGraphEdge::CallInstSet::iterator it = callInstSet.begin(), eit = callInstSet.end(); it!=eit; ++it)
166 {
167 const CallICFGNode* cs = *it;
168 if(!mssa->hasCHI(cs))
169 continue;
172 {
173 const ActualOUTSVFGNode* actualOut = SVFUtil::cast<ActualOUTSVFGNode>(getSVFGNode(*ait));
174 f << "srcSVFGNodeID: " << nodeId << " => " << "dstSVFGNodeID: " << actualOut->getId() << " >= FormalOUTSVFGNode" << "\n";
175 }
176 }
177 NodeID def = getDef(formalOut->getMRVer());
178 f << "srcSVFGNodeID: " << nodeId << " => " << "dstSVFGNodeID: " << def << " >= FormalOUTSVFGNode | intra" << "\n";
179 }
180 else if(const ActualINSVFGNode* actualIn = SVFUtil::dyn_cast<ActualINSVFGNode>(node))
181 {
182 NodeID def = getDef(actualIn->getMRVer());
183 f << "srcSVFGNodeID: " << nodeId << " => " << "dstSVFGNodeID: " << def << " >= ActualINSVFGNode" << "\n";
184
185 }
186 else if(const MSSAPHISVFGNode* phiNode = SVFUtil::dyn_cast<MSSAPHISVFGNode>(node))
187 {
188 for (MemSSA::PHI::OPVers::const_iterator it = phiNode->opVerBegin(), eit = phiNode->opVerEnd();
189 it != eit; it++)
190 {
191 const MRVer* op = it->second;
192 NodeID def = getDef(op);
193 f << "srcSVFGNodeID: " << nodeId << " => " << "dstSVFGNodeID: " << def << " >= PHISVFGNode | MVER: {" << *op << "}" << "\n";
194 }
195 }
196 }
197 // Job finish and close file
198 f.close();
199 if (f.good())
200 {
201 outs() << "\n";
202 return;
203 }
204}
205
206void SVFG::readFile(const string& filename)
207{
208 outs() << "Loading SVFG analysis results from '" << filename << "'...";
209 ifstream F(filename.c_str());
210 if (!F.is_open())
211 {
212 outs() << " error opening file for reading!\n";
213 return;
214 }
215
217 for (PAGEdge::PAGEdgeSetTy::iterator iter = stores.begin(), eiter =
218 stores.end(); iter != eiter; ++iter)
219 {
220 StoreStmt* store = SVFUtil::cast<StoreStmt>(*iter);
221 const StmtSVFGNode* sNode = getStmtVFGNode(store);
222 for(CHISet::iterator pi = mssa->getCHISet(store).begin(), epi = mssa->getCHISet(store).end(); pi!=epi; ++pi)
223 setDef((*pi)->getResVer(),sNode);
224 }
225 //outer loop through each line in the file
226 string line;
227 // add nodes
229 while (F.good())
230 {
231 getline(F, line);
232 if (line.empty())
233 continue;
234 if (line.find("__Edges__") != std::string::npos)
235 break;
236
237 std::string s = line;
238 std::string delimiter = " >= ";
239 string temp;
240 int index = 0;
241 //implement delimiter to split string using ">="
242 size_t next = 0;
243 size_t last = 0;
244 size_t outer_last = 0;
245 size_t nextTemp; //size_t lastTemp;
246 NodeID id = 0;
247 string type;
248 string MR;
249 string basicBlock;
250 string opVer;
251 //inner loop through to get each element in the line
252 while ((next = s.find(delimiter, last)) != string::npos)
253 {
254 temp = s.substr(last, next-last);
255 last = next + 4;
256 outer_last = next + 4;
257 if(index == 0)
258 {
259 nextTemp = temp.find("SVFGNodeID: ") + 12;
260 id = atoi(temp.substr(nextTemp).c_str());
261 }
262 if(index == 1)
263 {
264 type = temp;
265 }
266 if(index > 1)
267 {
268 if(index == 2)
269 {
270 MR = temp;
271 }
272 if(index == 3)
273 {
274 basicBlock = temp;
275 }
276 }
277 index++;
278 }
280 if(!MR.empty())
281 {
283 }
284 else
285 {
287 }
288 //add nodes using the variables we extracted
289 if(type == "FormalINSVFGNode")
290 {
291 outer_last = s.find("ICFGNodeID: ") + 12;
292 NodeID FunID = atoi(s.substr(outer_last).c_str());
293 addFormalINSVFGNode(SVFUtil::dyn_cast<FunEntryICFGNode>(pag->getICFG()->getICFGNode(FunID)), tempMRVer, id);
294 }
295 else if(type == "FormalOUTSVFGNode")
296 {
297 outer_last = s.find("ICFGNodeID: ") + 12;
298 NodeID FunID = atoi(s.substr(outer_last).c_str());
299 addFormalOUTSVFGNode(SVFUtil::dyn_cast<FunExitICFGNode>(pag->getICFG()->getICFGNode(FunID)), tempMRVer, id);
300 }
301 else if(type == "ActualINSVFGNode")
302 {
303 outer_last = s.find("ICFGNodeID: ") + 12;
304 NodeID CallSiteID = atoi(s.substr(outer_last).c_str());
305 addActualINSVFGNode(SVFUtil::dyn_cast<CallICFGNode>(pag->getICFG()->getICFGNode(CallSiteID)), tempMRVer, id);
306 }
307 else if(type == "ActualOUTSVFGNode")
308 {
309 outer_last = s.find("ICFGNodeID: ") + 12;
310 NodeID CallSiteID = atoi(s.substr(outer_last).c_str());
311 addActualOUTSVFGNode(SVFUtil::dyn_cast<CallICFGNode>(pag->getICFG()->getICFGNode(CallSiteID)), tempMRVer, id);
312 }
313 else if (type == "PHISVFGNode")
314 {
315 opVer = s.substr(outer_last);
316 next = opVer.find("{") + 1;
317 last = opVer.find(",}");
318 temp = opVer.substr(next, last);
320 int index = 0;
321 while ((next = temp.find("{") + 1) != string::npos)
322 {
323 if (temp == ",}")
324 break;
325 last = temp.find("},");
326 string temp1;
327 temp1 = temp.substr(next, last-next);
329 OPVers.insert(make_pair(index, tempOPVer));
330 temp = temp.substr(last + 1);
331 index++;
332 }
333 next = basicBlock.find("ICFGNodeID: ") + 12;
334 temp = basicBlock.substr(next);
335 addIntraMSSAPHISVFGNode(pag->getICFG()->getICFGNode(atoi(temp.c_str())), OPVers.begin(), OPVers.end(), tempMRVer, id);
336 }
337 else
338 {
339 }
340
341 if (totalVFGNode < id)
342 totalVFGNode = id + 1;
343 }
344 stat->ATVFNodeEnd();
345
347 // Edges
348 while (F.good())
349 {
350 getline(F, line);
351 if (line.empty())
352 continue;
353
354 std::string s = line;
355 std::string delimiter = " >= ";
356 string temp;
357 // int index = 0;
358 size_t last = 0;
359 size_t next = 0; // size_t outer_last = 0;
360 string edge;
361 string attributes;
362
363 next = s.find(delimiter);
364
365 edge = s.substr(0, next);
366 attributes = s.substr(next + 4);
367
368 // extract nodeIDs for src and dst nodes
369 NodeID src;
370 NodeID dst;
371 next = edge.find("srcSVFGNodeID: ") + 15;
372 last = edge.find(" => ");
373 src = atoi(edge.substr(next, last-next).c_str());
374 next = edge.find("dstSVFGNodeID: ") + 15;
375 dst = atoi(edge.substr(next).c_str());
376
377 string type;
378 string attribute;
379 if (attributes.find(" | ") == string::npos)
381 else
382 {
383 next = attributes.find(" | ");
384 type = attributes.substr(0, next);
385 attribute = attributes.substr(next + 3);
386 }
387
388 if(type == "FormalINSVFGNode")
389 {
390 const FormalINSVFGNode* formalIn = SVFUtil::cast<FormalINSVFGNode>(getSVFGNode(src));
391 const ActualINSVFGNode* actualIn = SVFUtil::cast<ActualINSVFGNode>(getSVFGNode(dst));
393 }
394 else if(type == "FormalOUTSVFGNode")
395 {
396 const FormalOUTSVFGNode* formalOut = SVFUtil::cast<FormalOUTSVFGNode>(getSVFGNode(src));
397 if (attribute.find("intra") != string::npos)
398 {
399 addIntraIndirectVFEdge(dst, src, formalOut->getMRVer()->getMR()->getPointsTo());
400 }
401 else
402 {
403 const ActualOUTSVFGNode* actualOut = SVFUtil::cast<ActualOUTSVFGNode>(getSVFGNode(dst));
405 }
406 }
407 else if(type == "ActualINSVFGNode")
408 {
409 const ActualINSVFGNode* actualIn = SVFUtil::cast<ActualINSVFGNode>(getSVFGNode(src));
410 addIntraIndirectVFEdge(dst,src, actualIn->getMRVer()->getMR()->getPointsTo());
411 }
412 else if(type == "ActualOUTSVFGNode")
413 {
414 // There's no need to connect actual out node to its definition site in the same function.
415 }
416 else if (type == "StoreNode" || type == "LoadNode" || type == "PHISVFGNode")
417 {
419 tempMRVer = getMRVERFromString(attribute);
420 addIntraIndirectVFEdge(dst,src, tempMRVer->getMR()->getPointsTo());
421 }
422 else
423 {
424 }
425 }
428}
429
431{
432 if(s == "")
433 {
434 return NULL;
435 }
436 string temp;
437 size_t last = 0;
438 size_t next = 0;
442 //{create Memory Region object
443 next = s.find("MemRegion: pts{") + 15;
444 last = s.find("} MRVERSION: ");
445 temp = s.substr(next, last-next);
446 // convert string to PointsTo
448 string point;
450 while (getline(ss, point, ' '))
451 {
453 NodeID obj;
454 sss >> obj;
455 dstPts.set(obj);
456 }
458 // create mssdef
459 next = s.find("MSSADef: ") + 9;
460 last = s.find("} >=");
461 temp = s.substr(next, last-next);
462 // convert string to deftype
463 istringstream ss1(temp.substr(0, temp.find(", ")));
464 int obj1;
465 ss1 >> obj1;
468 // mrversion
469 next = s.find("MRVERSION: ") + 11;
470 last = s.find(" MSSADef:");
471 temp = s.substr(next, last-next);
472 // convert mrversion to nodeid
474 NodeID obj2;
475 ss2 >> obj2;
476 // create mrver
478 return tempMRVer;
479}
item next
Definition cJSON.cpp:2224
newitem type
Definition cJSON.cpp:2739
int index
Definition cJSON.h:170
Set< const CallICFGNode * > CallInstSet
Definition CallGraph.h:55
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
const ICFGNode * front() const
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:163
SVFStmtSetTy PAGEdgeSetTy
NodeID getId() const
Get ID.
Definition SVFValue.h:158
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 FunObjVar *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:52
for isBitcode
Definition BasicTypes.h:68
unsigned CallSiteID
Definition GeneralType.h:58
u32_t NodeID
Definition GeneralType.h:56
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:74