Static Value-Flow Analysis
Loading...
Searching...
No Matches
CFLGraphBuilder.cpp
Go to the documentation of this file.
1//===----- CFLGraphBuilder.h -- CFL Graph Builder--------------//
2//
3// SVF: Static Value-Flow Analysis
4//
5// Copyright (C) <2013-> <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 * CFLGraphBuilder.h
25 *
26 * Created on: May 22, 2022
27 * Author: Pei Xu
28 */
29
30#include "CFL/CFLGraphBuilder.h"
31#include "Util/Options.h"
32#include "SVFIR/SVFValue.h"
33
34namespace SVF
35{
38{
39 if (kindToAttrsMap.find(kind) == kindToAttrsMap.end())
40 {
42 kindToAttrsMap.insert(make_pair(kind, attrs));
43 }
44 else
45 {
46 if (kindToAttrsMap[kind].find(attribute) == kindToAttrsMap[kind].end())
47 {
48 kindToAttrsMap[kind].insert(attribute);
49 }
50 }
51}
52
55{
56 for(auto pairV : grammar->getTerminals())
57 {
58 if(labelToKindMap.find(pairV.first) == labelToKindMap.end())
59 {
60 labelToKindMap.insert(pairV);
61 }
62 if(kindToLabelMap.find(pairV.second) == kindToLabelMap.end())
63 {
64 kindToLabelMap.insert(make_pair(pairV.second, pairV.first));
65 }
66 }
67
68 for(auto pairV : grammar->getNonterminals())
69 {
70 if(labelToKindMap.find(pairV.first) == labelToKindMap.end())
71 {
72 labelToKindMap.insert(pairV);
73 }
74 if(kindToLabelMap.find(pairV.second) == kindToLabelMap.end())
75 {
76 kindToLabelMap.insert(make_pair(pairV.second, pairV.first));
77 }
78 }
79}
80
83{
85 if (cflGraph->hasGNode(NodeID)==false)
86 {
87 cflNode = new CFLNode(NodeID);
89 }
90 else
91 {
93 }
94 return cflNode;
95}
96
97
100template<class N, class E>
102{
103 cflGraph = new CFLGraph(grammar->getStartKind());
104 // buildlabelToKindMap(grammar);
105 for(auto it = graph->begin(); it!= graph->end(); it++)
106 {
107 CFLNode* node = new CFLNode((*it).first);
108 cflGraph->addCFLNode((*it).first, node);
109 }
110 for(auto it = graph->begin(); it!= graph->end(); it++)
111 {
112 N* node = (*it).second;
113 for(E* edge : node->getOutEdges())
114 {
115 CFGrammar::Kind edgeLabel = edge->getEdgeKind();
116 cflGraph->addCFLEdge(cflGraph->getGNode(edge->getSrcID()), cflGraph->getGNode(edge->getDstID()), edgeLabel);
118 {
119 std::string label = grammar->kindToStr(edge);
120 label.append("bar");
121 cflGraph->addCFLEdge(cflGraph->getGNode(edge->getDstID()), cflGraph->getGNode(edge->getSrcID()), grammar->strToKind(label));
122 }
123 }
124 }
125 return cflGraph;
126}
127
129{
130 bool isDot = (fileName.rfind(".dot") == fileName.length() - std::string(".dot").length());
131 if (isDot)
132 return buildFromDot(fileName, grammar, direction);
133
134 bool isJson = (fileName.rfind(".json") == fileName.length() - std::string(".json").length());
135 if (isJson)
136 return buildFromJson(fileName, grammar, direction);
137
138 return buildFromText(fileName, grammar, direction);
139}
140
143{
144 buildlabelToKindMap(grammar);
145 cflGraph = new CFLGraph(grammar->getStartKind());
146
147 std::cout << "Building CFL Graph from text file: " << fileName << "..\n";
148 std::string lineString;
149 std::ifstream inputFile(fileName);
150
151 if (!inputFile.is_open())
152 {
153 SVFUtil::errs() << "Error opening " << fileName << std::endl;
154 abort();
155 }
156
157 std::string line;
158 current = labelToKindMap.size();
159 u32_t lineNum = 0 ;
160
161 while (getline(inputFile, line))
162 {
163 std::vector<std::string> vec = SVFUtil::split(line, '\t');
164 if (vec.empty())
165 continue;
166 lineNum += 1;
167 NodeID srcID = std::stoi(vec[0]);
168 NodeID dstID = std::stoi(vec[1]);
169 CFLNode *src = addGNode(srcID);
170 CFLNode *dst = addGNode(dstID);
171 std::string label = vec[2];
172 if (labelToKindMap.find(label) != labelToKindMap.end())
174 else
175 {
176 if(Options::FlexSymMap() == true)
177 {
178 labelToKindMap.insert({label, current++});
180 }
181 else
182 {
183 std::string msg = "In line " + std::to_string(lineNum) +
184 " sym can not find in grammar, please correct the input dot or set --flexsymmap.";
186 std::cout << msg;
187 abort();
188 }
189 }
190 }
191
192 inputFile.close();
193 return cflGraph;
194}
195
197{
198 buildlabelToKindMap(grammar);
199 cflGraph = new CFLGraph(grammar->getStartKind());
200 std::string lineString;
201 std::ifstream inputFile(fileName);
202 std::cout << "Building CFL Graph from dot file: " << fileName << "..\n";
203 std::cout << std::boolalpha;
204
205 u32_t lineNum = 0;
206 current = labelToKindMap.size();
207
209 {
210 lineNum += 1;
211
212 // Find "Node" prefixes and "->"
213 size_t srcStart = lineString.find("Node");
214 if (srcStart == std::string::npos) continue;
215
216 size_t srcEnd = lineString.find(" ", srcStart);
217 if (srcEnd == std::string::npos) continue;
218
219 size_t arrowPos = lineString.find("->", srcEnd);
220 if (arrowPos == std::string::npos) continue;
221
222 size_t dstStart = lineString.find("Node", arrowPos);
223 if (dstStart == std::string::npos) continue;
224
225 size_t dstEnd = lineString.find(" ", dstStart);
226 if (dstEnd == std::string::npos) continue;
227
228 size_t labelStart = lineString.find("label=", dstEnd);
229 if (labelStart == std::string::npos) continue;
230
231 labelStart += 6; // Move past "label=" to the start of the label
232 size_t labelEnd = lineString.find_first_of("]", labelStart);
233 if (labelEnd == std::string::npos) continue;
234
235 // Extract the source ID, destination ID, and label
236 std::string srcIDStr = lineString.substr(srcStart + 4, srcEnd - (srcStart + 4));
237 std::string dstIDStr = lineString.substr(dstStart + 4, dstEnd - (dstStart + 4));
238 std::string label = lineString.substr(labelStart, labelEnd - labelStart);
239
240 // Convert source and destination IDs from hexadecimal
241 u32_t srcID = std::stoul(srcIDStr, nullptr, 16);
242 u32_t dstID = std::stoul(dstIDStr, nullptr, 16);
243
244 CFLNode *src = addGNode(srcID);
245 CFLNode *dst = addGNode(dstID);
246
247 if (labelToKindMap.find(label) != labelToKindMap.end())
248 {
250 }
251 else
252 {
253 if (Options::FlexSymMap() == true)
254 {
255 labelToKindMap.insert({label, current++});
257 }
258 else
259 {
260 std::string msg = "In line " + std::to_string(lineNum) +
261 " sym cannot be found in grammar. Please correct the input dot or set --flexsymmap.";
263 std::cout << msg;
264 abort();
265 }
266 }
267 }
268
269 inputFile.close();
270 return cflGraph;
271}
272
275{
276 cflGraph = new CFLGraph(grammar->getStartKind());
277 return cflGraph;
278}
279
281{
282 cflGraph = new CFLGraph(startKind);
283
284 buildlabelToKindMap(grammar);
285 for(auto it = graph->begin(); it!= graph->end(); it++)
286 {
287 CFLNode* node = new CFLNode((*it).first);
288 cflGraph->addCFLNode((*it).first, node);
289 }
290 for(auto it = graph->begin(); it!= graph->end(); it++)
291 {
292 ConstraintNode* node = (*it).second;
293 for(ConstraintEdge* edge : node->getOutEdges())
294 {
295 CFGrammar::Kind edgeLabel = edge->getEdgeKind();
296 // Need to get the offset from the Const Edge
297 // The offset present edge is only from Normal Gep CG at moment
299 {
300 NormalGepCGEdge *nGepEdge = SVFUtil::dyn_cast<NormalGepCGEdge>(edge);
301 CFGrammar::Attribute attr = nGepEdge->getConstantFieldIdx();
304 cflGraph->addCFLEdge(cflGraph->getGNode(edge->getSrcID()), cflGraph->getGNode(edge->getDstID()), edgeLabel);
305 std::string label = kindToLabelMap[edge->getEdgeKind()];
306 label.append("bar"); // for example Gep_i should be Gepbar_i, not Gep_ibar
309 }
310 else
311 {
312 cflGraph->addCFLEdge(cflGraph->getGNode(edge->getSrcID()), cflGraph->getGNode(edge->getDstID()), edgeLabel);
313 std::string label = kindToLabelMap[edge->getEdgeKind()];
314 label.append("bar");
316 }
317 }
318 }
319 return cflGraph;
320}
321
323{
324 cflGraph = new CFLGraph(startKind);
325
326 buildlabelToKindMap(grammar);
327 for(auto it = graph->begin(); it!= graph->end(); it++)
328 {
329 CFLNode* node = new CFLNode((*it).first);
330 cflGraph->addCFLNode((*it).first, node);
331 }
332 for(auto it = graph->begin(); it!= graph->end(); it++)
333 {
334 ConstraintNode* node = (*it).second;
335 for(ConstraintEdge* edge : node->getOutEdges())
336 {
338 if (edge->getEdgeKind() == ConstraintEdge::Store)
339 {
340 if (pag->isNullPtr(edge->getSrcID()))
341 continue;
343 ConstraintNode* Dst = edge->getDstNode();
344 ConstraintNode* DerefNode = nullptr;
345 CFLNode* CFLDerefNode = nullptr;
346 for (ConstraintEdge* DstInEdge : Dst->getInEdges())
347 {
348 if (DstInEdge->getEdgeKind() == ConstraintEdge::Addr)
349 {
350 DerefNode = DstInEdge->getSrcNode();
351 CFLDerefNode = cflGraph->getGNode(DstInEdge->getSrcID());
352 break;
353 }
354 }
355 if (DerefNode == nullptr)
356 {
357
364 label.append("bar");
366 }
370 label.append("bar");
372 }
374 else if ( edge->getEdgeKind() == ConstraintEdge::Load)
375 {
377 ConstraintNode* Src = edge->getSrcNode();
378 ConstraintNode* DerefNode = nullptr;
379 CFLNode* CFLDerefNode = nullptr;
380 for (ConstraintEdge* SrcInEdge : Src->getInEdges())
381 {
382 if (SrcInEdge->getEdgeKind() == ConstraintEdge::Addr)
383 {
384 DerefNode = SrcInEdge->getSrcNode();
385 CFLDerefNode = cflGraph->getGNode(SrcInEdge->getSrcID());
386 }
387 }
388 if (DerefNode == nullptr)
389 {
396 label.append("bar");
398 }
402 label.append("bar");
404 }
405 else if ( edge->getEdgeKind() == ConstraintEdge::VariantGep)
406 {
411 connectVGep(cflGraph, graph, edge->getSrcNode(), edge->getDstNode(), 8, pag);
412 }
413 else
414 {
415 CFGrammar::Kind edgeLabel = edge->getEdgeKind();
416 // Need to get the offset from the Const Edge
417 // The offset present edge is only from Normal Gep CG at moment
419 {
420 NormalGepCGEdge *nGepEdge = SVFUtil::dyn_cast<NormalGepCGEdge>(edge);
421 CFGrammar::Attribute attr = nGepEdge->getConstantFieldIdx();
424 cflGraph->addCFLEdge(cflGraph->getGNode(edge->getSrcID()), cflGraph->getGNode(edge->getDstID()), edgeLabel);
425 std::string label = kindToLabelMap[edge->getEdgeKind()];
426 label.append("bar"); // for example Gep_i should be Gepbar_i, not Gep_ibar
429 }
430 else
431 {
432 cflGraph->addCFLEdge(cflGraph->getGNode(edge->getSrcID()), cflGraph->getGNode(edge->getDstID()), edgeLabel);
433 std::string label = kindToLabelMap[edge->getEdgeKind()];
434 label.append("bar");
436 }
437 }
438 }
439 }
440 return cflGraph;
441}
442
443void AliasCFLGraphBuilder::AliasCFLGraphBuilder::connectVGep(CFLGraph *cflGraph, ConstraintGraph *graph, ConstraintNode *src, ConstraintNode *dst, u32_t level, SVFIR* pag)
444{
445 if (level == 0) return;
446 level -= 1;
447 for (auto eit = src->getAddrInEdges().begin(); eit != src->getAddrInEdges().end(); eit++)
448 {
449 const MemObj* mem = pag->getBaseObj((*eit)->getSrcID());
450 for (u32_t maxField = 0 ; maxField < mem->getNumOfElements(); maxField++)
451 {
452 addBiGepCFLEdge(cflGraph, (*eit)->getDstNode(), dst, maxField);
453 }
454 }
455 for (auto eit = src->getInEdges().begin(); eit != src->getInEdges().end() && level != 0; eit++)
456 {
457 connectVGep(cflGraph, graph, (*eit)->getSrcNode(), dst, level, pag);
458 }
459 return;
460}
461
463{
464 cflGraph->addCFLEdge(cflGraph->getGNode(src->getId()), cflGraph->getGNode(dst->getId()), kind);
465 std::string label = kindToLabelMap[kind];
466 label.append("bar");
468 return;
469}
470
480
482{
483 cflGraph = new CFLGraph(startKind);
484
485 buildlabelToKindMap(grammar);
486 for(auto it = graph->begin(); it!= graph->end(); it++)
487 {
488 CFLNode* node = new CFLNode((*it).first);
489 cflGraph->addCFLNode((*it).first, node);
490 }
491 for(auto it = graph->begin(); it!= graph->end(); it++)
492 {
493 VFGNode* node = (*it).second;
494 for(VFGEdge* edge : node->getOutEdges())
495 {
497 // Get 'a' edge : IntraDirectVF || IntraIndirectVF
498 if (edge->getEdgeKind() == VFGEdge::IntraDirectVF || edge->getEdgeKind() == VFGEdge::IntraIndirectVF || edge->getEdgeKind() == VFGEdge::TheadMHPIndirectVF )
499 {
500 edgeLabel = 0;
501 cflGraph->addCFLEdge(cflGraph->getGNode(edge->getSrcID()), cflGraph->getGNode(edge->getDstID()), edgeLabel);
502 cflGraph->addCFLEdge(cflGraph->getGNode(edge->getSrcID()), cflGraph->getGNode(edge->getDstID()), edgeLabel);
503 std::string label = kindToLabelMap[edge->getEdgeKind()];
504 label.append("bar");
506 }
507 // Get 'call' edge : CallDirVF || CallIndVF
508 else if ( edge->getEdgeKind() == VFGEdge::CallDirVF )
509 {
510 edgeLabel = 1;
511 CallDirSVFGEdge *attributedEdge = SVFUtil::dyn_cast<CallDirSVFGEdge>(edge);
512 CFGrammar::Attribute attr = attributedEdge->getCallSiteId();
515 cflGraph->addCFLEdge(cflGraph->getGNode(edge->getSrcID()), cflGraph->getGNode(edge->getDstID()), edgeLabel);
516 std::string label = kindToLabelMap[edgeLabel];
517 label.append("bar"); // for example Gep_i should be Gepbar_i, not Gep_ibar
520 }
521 // Get 'call' edge : CallIndVF
522 else if ( edge->getEdgeKind() == VFGEdge::CallIndVF )
523 {
524 edgeLabel = 1;
525 CallIndSVFGEdge *attributedEdge = SVFUtil::dyn_cast<CallIndSVFGEdge>(edge);
526 CFGrammar::Attribute attr = attributedEdge->getCallSiteId();
529 cflGraph->addCFLEdge(cflGraph->getGNode(edge->getSrcID()), cflGraph->getGNode(edge->getDstID()), edgeLabel);
530 std::string label = kindToLabelMap[edgeLabel];
531 label.append("bar"); // for example Gep_i should be Gepbar_i, not Gep_ibar
534 }
535 // Get 'ret' edge : RetDirVF
536 else if ( edge->getEdgeKind() == VFGEdge::RetDirVF )
537 {
538 edgeLabel = 2;
539 RetDirSVFGEdge *attributedEdge = SVFUtil::dyn_cast<RetDirSVFGEdge>(edge);
540 CFGrammar::Attribute attr = attributedEdge->getCallSiteId();
543 cflGraph->addCFLEdge(cflGraph->getGNode(edge->getSrcID()), cflGraph->getGNode(edge->getDstID()), edgeLabel);
544 std::string label = kindToLabelMap[edgeLabel];
545 label.append("bar"); // for example Gep_i should be Gepbar_i, not Gep_ibar
548 }
549 // Get 'ret' edge : RetIndVF
550 else if ( edge->getEdgeKind() == VFGEdge::RetIndVF )
551 {
552 edgeLabel = 2;
553 RetIndSVFGEdge *attributedEdge = SVFUtil::dyn_cast<RetIndSVFGEdge>(edge);
554 CFGrammar::Attribute attr = attributedEdge->getCallSiteId();
557 cflGraph->addCFLEdge(cflGraph->getGNode(edge->getSrcID()), cflGraph->getGNode(edge->getDstID()), edgeLabel);
558 std::string label = kindToLabelMap[edgeLabel];
559 label.append("bar"); // for example Gep_i should be Gepbar_i, not Gep_ibar
562 }
563 }
564 }
565 return cflGraph;
566}
567
569{
570 CFLGraph *cflGraph = new CFLGraph(startKind);
571 return cflGraph;
572}
573
574
575} // end of SVF namespace
void addBiCFLEdge(CFLGraph *cflGraph, ConstraintNode *src, ConstraintNode *dst, CFGrammar::Kind label)
Handles edges, with the exception of the GEP.
void connectVGep(CFLGraph *cflGraph, ConstraintGraph *graph, ConstraintNode *src, ConstraintNode *dst, u32_t level, SVFIR *pag)
Connects VGep (Variable GEP)
void addBiGepCFLEdge(CFLGraph *cflGraph, ConstraintNode *src, ConstraintNode *dst, CFGrammar::Attribute attri)
Adds bidirectional GEP edges with attributes.
CFLGraph * buildBigraph(ConstraintGraph *graph, Kind startKind, GrammarBase *grammar)
Builds a bidirectional CFL graph by copying nodes and edges from a const graph that inherits from Gen...
CFLGraph * buildBiPEGgraph(ConstraintGraph *graph, Kind startKind, GrammarBase *grammar, SVFIR *pag)
void buildlabelToKindMap(GrammarBase *grammar)
build label and kind connect from the grammar
CFLGraph * buildFromDot(std::string filename, GrammarBase *grammar, BuildDirection direction=BuildDirection::plain)
Method to build a CFL graph from a Dot file.
Map< std::string, Kind > labelToKindMap
Maps to maintain mapping between labels and kinds.
CFLGraph * build(GenericGraph< N, E > *graph, GrammarBase *grammar, BuildDirection direction=BuildDirection::plain)
CFGrammar::Kind Kind
Map< Kind, std::string > kindToLabelMap
CFLGraph * buildFromJson(std::string filename, GrammarBase *grammar, BuildDirection direction=BuildDirection::plain)
Method to build a CFL graph from a Json file.
CFLGraph * buildFromText(std::string fileName, GrammarBase *grammar, BuildDirection direction=BuildDirection::plain)
Method to build a CFL graph from a Text file.
CFLNode * addGNode(u32_t NodeID)
add src and dst node from file
void addAttribute(CFGrammar::Kind kind, CFGrammar::Attribute attribute)
Method to add an attribute to a specific kind.
Map< CFGrammar::Kind, Set< CFGrammar::Attribute > > kindToAttrsMap
Map to maintain attributes associated with each kind.
virtual void addCFLNode(NodeID id, CFLNode *node)
Definition CFLGraph.cpp:42
virtual const CFLEdge * addCFLEdge(CFLNode *src, CFLNode *dst, CFLEdge::GEdgeFlag label)
Definition CFLGraph.cpp:47
const ConstraintEdge::ConstraintEdgeSetTy & getAddrInEdges() const
Definition ConsGNode.h:143
iterator begin()
Iterators.
bool hasGNode(NodeID id) const
Has a node.
NodeType * getGNode(NodeID id) const
Get a node.
const GEdgeSetTy & getOutEdges() const
const GEdgeSetTy & getInEdges() const
Kind strToKind(std::string str) const
Definition CFGrammar.cpp:55
Map< std::string, Kind > & getNonterminals()
Definition CFGrammar.h:160
Map< std::string, Kind > & getTerminals()
Definition CFGrammar.h:170
Kind getStartKind()
Definition CFGrammar.h:205
std::string kindToStr(Kind kind) const
static Kind getAttributedKind(Attribute attribute, Kind kind)
Definition CFGrammar.h:265
u32_t getNumOfElements() const
Get the number of elements of this object.
static bool classof(const NormalGepCGEdge *)
Methods for support type inquiry through isa, cast, and dyn_cast:
Definition ConsGEdge.h:277
static const Option< bool > FlexSymMap
Definition Options.h:234
NodeID getId() const
Get ID.
bool isNullPtr(NodeID id) const
Definition SVFIR.h:453
const MemObj * getBaseObj(NodeID id) const
Definition SVFIR.h:481
NodeID addDummyValNode()
Definition SVFIR.h:496
CFLGraph * buildBiPEGgraph(ConstraintGraph *graph, Kind startKind, GrammarBase *grammar, SVFIR *pag)
CFLGraph * buildBigraph(SVFG *graph, Kind startKind, GrammarBase *grammar)
Builds a bidirectional CFL graph by copying nodes and edges from a const graph that inherits from SVF...
@ IntraDirectVF
Definition VFGEdge.h:53
@ IntraIndirectVF
Definition VFGEdge.h:54
@ TheadMHPIndirectVF
Definition VFGEdge.h:59
std::string errMsg(const std::string &msg)
Print error message by converting a string into red string output.
Definition SVFUtil.cpp:77
std::ostream & errs()
Overwrite llvm::errs()
Definition SVFUtil.h:56
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:203
for isBitcode
Definition BasicTypes.h:68
u32_t NodeID
Definition GeneralType.h:55
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:74
unsigned u32_t
Definition GeneralType.h:46