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
33namespace SVF
34{
37{
38 if (kindToAttrsMap.find(kind) == kindToAttrsMap.end())
39 {
41 kindToAttrsMap.insert(make_pair(kind, attrs));
42 }
43 else
44 {
45 if (kindToAttrsMap[kind].find(attribute) == kindToAttrsMap[kind].end())
46 {
47 kindToAttrsMap[kind].insert(attribute);
48 }
49 }
50}
51
54{
55 for(auto pairV : grammar->getTerminals())
56 {
57 if(labelToKindMap.find(pairV.first) == labelToKindMap.end())
58 {
59 labelToKindMap.insert(pairV);
60 }
61 if(kindToLabelMap.find(pairV.second) == kindToLabelMap.end())
62 {
63 kindToLabelMap.insert(make_pair(pairV.second, pairV.first));
64 }
65 }
66
67 for(auto pairV : grammar->getNonterminals())
68 {
69 if(labelToKindMap.find(pairV.first) == labelToKindMap.end())
70 {
71 labelToKindMap.insert(pairV);
72 }
73 if(kindToLabelMap.find(pairV.second) == kindToLabelMap.end())
74 {
75 kindToLabelMap.insert(make_pair(pairV.second, pairV.first));
76 }
77 }
78}
79
82{
84 if (cflGraph->hasGNode(NodeID)==false)
85 {
86 cflNode = new CFLNode(NodeID);
88 }
89 else
90 {
92 }
93 return cflNode;
94}
95
96
99template<class N, class E>
101{
102 cflGraph = new CFLGraph(grammar->getStartKind());
103 // buildlabelToKindMap(grammar);
104 for(auto it = graph->begin(); it!= graph->end(); it++)
105 {
106 CFLNode* node = new CFLNode((*it).first);
107 cflGraph->addCFLNode((*it).first, node);
108 }
109 for(auto it = graph->begin(); it!= graph->end(); it++)
110 {
111 N* node = (*it).second;
112 for(E* edge : node->getOutEdges())
113 {
114 CFGrammar::Kind edgeLabel = edge->getEdgeKind();
115 cflGraph->addCFLEdge(cflGraph->getGNode(edge->getSrcID()), cflGraph->getGNode(edge->getDstID()), edgeLabel);
117 {
118 std::string label = grammar->kindToStr(edge);
119 label.append("bar");
120 cflGraph->addCFLEdge(cflGraph->getGNode(edge->getDstID()), cflGraph->getGNode(edge->getSrcID()), grammar->strToKind(label));
121 }
122 }
123 }
124 return cflGraph;
125}
126
128{
129 bool isDot = (fileName.rfind(".dot") == fileName.length() - std::string(".dot").length());
130 if (isDot)
131 return buildFromDot(fileName, grammar, direction);
132
133 bool isJson = (fileName.rfind(".json") == fileName.length() - std::string(".json").length());
134 if (isJson)
135 return buildFromJson(fileName, grammar, direction);
136
137 return buildFromText(fileName, grammar, direction);
138}
139
142{
143 buildlabelToKindMap(grammar);
144 cflGraph = new CFLGraph(grammar->getStartKind());
145
146 std::cout << "Building CFL Graph from text file: " << fileName << "..\n";
147 std::string lineString;
148 std::ifstream inputFile(fileName);
149
150 if (!inputFile.is_open())
151 {
152 SVFUtil::errs() << "Error opening " << fileName << std::endl;
153 abort();
154 }
155
156 std::string line;
157 current = labelToKindMap.size();
158 u32_t lineNum = 0 ;
159
160 while (getline(inputFile, line))
161 {
162 std::vector<std::string> vec = SVFUtil::split(line, '\t');
163 if (vec.empty())
164 continue;
165 lineNum += 1;
166 NodeID srcID = std::stoi(vec[0]);
167 NodeID dstID = std::stoi(vec[1]);
168 CFLNode *src = addGNode(srcID);
169 CFLNode *dst = addGNode(dstID);
170 std::string label = vec[2];
171 if (labelToKindMap.find(label) != labelToKindMap.end())
173 else
174 {
175 if(Options::FlexSymMap() == true)
176 {
177 labelToKindMap.insert({label, current++});
179 }
180 else
181 {
182 std::string msg = "In line " + std::to_string(lineNum) +
183 " sym can not find in grammar, please correct the input dot or set --flexsymmap.";
185 std::cout << msg;
186 abort();
187 }
188 }
189 }
190
191 inputFile.close();
192 return cflGraph;
193}
194
196{
197 buildlabelToKindMap(grammar);
198 cflGraph = new CFLGraph(grammar->getStartKind());
199 std::string lineString;
200 std::ifstream inputFile(fileName);
201 std::cout << "Building CFL Graph from dot file: " << fileName << "..\n";
202 std::cout << std::boolalpha;
203
204 u32_t lineNum = 0;
205 current = labelToKindMap.size();
206
208 {
209 lineNum += 1;
210
211 // Find "Node" prefixes and "->"
212 size_t srcStart = lineString.find("Node");
213 if (srcStart == std::string::npos) continue;
214
215 size_t srcEnd = lineString.find(" ", srcStart);
216 if (srcEnd == std::string::npos) continue;
217
218 size_t arrowPos = lineString.find("->", srcEnd);
219 if (arrowPos == std::string::npos) continue;
220
221 size_t dstStart = lineString.find("Node", arrowPos);
222 if (dstStart == std::string::npos) continue;
223
224 size_t dstEnd = lineString.find(" ", dstStart);
225 if (dstEnd == std::string::npos) continue;
226
227 size_t labelStart = lineString.find("label=", dstEnd);
228 if (labelStart == std::string::npos) continue;
229
230 labelStart += 6; // Move past "label=" to the start of the label
231 size_t labelEnd = lineString.find_first_of("]", labelStart);
232 if (labelEnd == std::string::npos) continue;
233
234 // Extract the source ID, destination ID, and label
235 std::string srcIDStr = lineString.substr(srcStart + 4, srcEnd - (srcStart + 4));
236 std::string dstIDStr = lineString.substr(dstStart + 4, dstEnd - (dstStart + 4));
237 std::string label = lineString.substr(labelStart, labelEnd - labelStart);
238
239 // Convert source and destination IDs from hexadecimal
240 u32_t srcID = std::stoul(srcIDStr, nullptr, 16);
241 u32_t dstID = std::stoul(dstIDStr, nullptr, 16);
242
243 CFLNode *src = addGNode(srcID);
244 CFLNode *dst = addGNode(dstID);
245
246 if (labelToKindMap.find(label) != labelToKindMap.end())
247 {
249 }
250 else
251 {
252 if (Options::FlexSymMap() == true)
253 {
254 labelToKindMap.insert({label, current++});
256 }
257 else
258 {
259 std::string msg = "In line " + std::to_string(lineNum) +
260 " sym cannot be found in grammar. Please correct the input dot or set --flexsymmap.";
262 std::cout << msg;
263 abort();
264 }
265 }
266 }
267
268 inputFile.close();
269 return cflGraph;
270}
271
274{
275 cflGraph = new CFLGraph(grammar->getStartKind());
276 return cflGraph;
277}
278
280{
281 cflGraph = new CFLGraph(startKind);
282
283 buildlabelToKindMap(grammar);
284 for(auto it = graph->begin(); it!= graph->end(); it++)
285 {
286 CFLNode* node = new CFLNode((*it).first);
287 cflGraph->addCFLNode((*it).first, node);
288 }
289 for(auto it = graph->begin(); it!= graph->end(); it++)
290 {
291 ConstraintNode* node = (*it).second;
292 for(ConstraintEdge* edge : node->getOutEdges())
293 {
294 CFGrammar::Kind edgeLabel = edge->getEdgeKind();
295 // Need to get the offset from the Const Edge
296 // The offset present edge is only from Normal Gep CG at moment
298 {
299 NormalGepCGEdge *nGepEdge = SVFUtil::dyn_cast<NormalGepCGEdge>(edge);
300 CFGrammar::Attribute attr = nGepEdge->getConstantFieldIdx();
303 cflGraph->addCFLEdge(cflGraph->getGNode(edge->getSrcID()), cflGraph->getGNode(edge->getDstID()), edgeLabel);
304 std::string label = kindToLabelMap[edge->getEdgeKind()];
305 label.append("bar"); // for example Gep_i should be Gepbar_i, not Gep_ibar
308 }
309 else
310 {
311 cflGraph->addCFLEdge(cflGraph->getGNode(edge->getSrcID()), cflGraph->getGNode(edge->getDstID()), edgeLabel);
312 std::string label = kindToLabelMap[edge->getEdgeKind()];
313 label.append("bar");
315 }
316 }
317 }
318 return cflGraph;
319}
320
322{
323 cflGraph = new CFLGraph(startKind);
324
325 buildlabelToKindMap(grammar);
326 for(auto it = graph->begin(); it!= graph->end(); it++)
327 {
328 CFLNode* node = new CFLNode((*it).first);
329 cflGraph->addCFLNode((*it).first, node);
330 }
331 for(auto it = graph->begin(); it!= graph->end(); it++)
332 {
333 ConstraintNode* node = (*it).second;
334 for(ConstraintEdge* edge : node->getOutEdges())
335 {
337 if (edge->getEdgeKind() == ConstraintEdge::Store)
338 {
339 if (pag->isNullPtr(edge->getSrcID()))
340 continue;
342 ConstraintNode* Dst = edge->getDstNode();
343 ConstraintNode* DerefNode = nullptr;
344 CFLNode* CFLDerefNode = nullptr;
345 for (ConstraintEdge* DstInEdge : Dst->getInEdges())
346 {
347 if (DstInEdge->getEdgeKind() == ConstraintEdge::Addr)
348 {
349 DerefNode = DstInEdge->getSrcNode();
350 CFLDerefNode = cflGraph->getGNode(DstInEdge->getSrcID());
351 break;
352 }
353 }
354 if (DerefNode == nullptr)
355 {
362 label.append("bar");
364 }
368 label.append("bar");
370 }
372 else if ( edge->getEdgeKind() == ConstraintEdge::Load)
373 {
375 ConstraintNode* Src = edge->getSrcNode();
376 ConstraintNode* DerefNode = nullptr;
377 CFLNode* CFLDerefNode = nullptr;
378 for (ConstraintEdge* SrcInEdge : Src->getInEdges())
379 {
380 if (SrcInEdge->getEdgeKind() == ConstraintEdge::Addr)
381 {
382 DerefNode = SrcInEdge->getSrcNode();
383 CFLDerefNode = cflGraph->getGNode(SrcInEdge->getSrcID());
384 }
385 }
386 if (DerefNode == nullptr)
387 {
394 label.append("bar");
396 }
400 label.append("bar");
402 }
403 else if ( edge->getEdgeKind() == ConstraintEdge::VariantGep)
404 {
409 connectVGep(cflGraph, graph, edge->getSrcNode(), edge->getDstNode(), 8, pag);
410 }
411 else
412 {
413 CFGrammar::Kind edgeLabel = edge->getEdgeKind();
414 // Need to get the offset from the Const Edge
415 // The offset present edge is only from Normal Gep CG at moment
417 {
418 NormalGepCGEdge *nGepEdge = SVFUtil::dyn_cast<NormalGepCGEdge>(edge);
419 CFGrammar::Attribute attr = nGepEdge->getConstantFieldIdx();
422 cflGraph->addCFLEdge(cflGraph->getGNode(edge->getSrcID()), cflGraph->getGNode(edge->getDstID()), edgeLabel);
423 std::string label = kindToLabelMap[edge->getEdgeKind()];
424 label.append("bar"); // for example Gep_i should be Gepbar_i, not Gep_ibar
427 }
428 else
429 {
430 cflGraph->addCFLEdge(cflGraph->getGNode(edge->getSrcID()), cflGraph->getGNode(edge->getDstID()), edgeLabel);
431 std::string label = kindToLabelMap[edge->getEdgeKind()];
432 label.append("bar");
434 }
435 }
436 }
437 }
438 return cflGraph;
439}
440
441void AliasCFLGraphBuilder::AliasCFLGraphBuilder::connectVGep(CFLGraph *cflGraph, ConstraintGraph *graph, ConstraintNode *src, ConstraintNode *dst, u32_t level, SVFIR* pag)
442{
443 if (level == 0) return;
444 level -= 1;
445 for (auto eit = src->getAddrInEdges().begin(); eit != src->getAddrInEdges().end(); eit++)
446 {
447 const BaseObjVar* baseObj = pag->getBaseObject((*eit)->getSrcID());
448 for (u32_t maxField = 0 ; maxField < baseObj->getNumOfElements(); maxField++)
449 {
450 addBiGepCFLEdge(cflGraph, (*eit)->getDstNode(), dst, maxField);
451 }
452 }
453 for (auto eit = src->getInEdges().begin(); eit != src->getInEdges().end() && level != 0; eit++)
454 {
455 connectVGep(cflGraph, graph, (*eit)->getSrcNode(), dst, level, pag);
456 }
457 return;
458}
459
461{
462 cflGraph->addCFLEdge(cflGraph->getGNode(src->getId()), cflGraph->getGNode(dst->getId()), kind);
463 std::string label = kindToLabelMap[kind];
464 label.append("bar");
466 return;
467}
468
478
480{
481 cflGraph = new CFLGraph(startKind);
482
483 buildlabelToKindMap(grammar);
484 for(auto it = graph->begin(); it!= graph->end(); it++)
485 {
486 CFLNode* node = new CFLNode((*it).first);
487 cflGraph->addCFLNode((*it).first, node);
488 }
489 for(auto it = graph->begin(); it!= graph->end(); it++)
490 {
491 VFGNode* node = (*it).second;
492 for(VFGEdge* edge : node->getOutEdges())
493 {
495 // Get 'a' edge : IntraDirectVF || IntraIndirectVF
496 if (edge->getEdgeKind() == VFGEdge::IntraDirectVF || edge->getEdgeKind() == VFGEdge::IntraIndirectVF || edge->getEdgeKind() == VFGEdge::TheadMHPIndirectVF )
497 {
498 edgeLabel = 0;
499 cflGraph->addCFLEdge(cflGraph->getGNode(edge->getSrcID()), cflGraph->getGNode(edge->getDstID()), edgeLabel);
500 cflGraph->addCFLEdge(cflGraph->getGNode(edge->getSrcID()), cflGraph->getGNode(edge->getDstID()), edgeLabel);
501 std::string label = kindToLabelMap[edge->getEdgeKind()];
502 label.append("bar");
504 }
505 // Get 'call' edge : CallDirVF || CallIndVF
506 else if ( edge->getEdgeKind() == VFGEdge::CallDirVF )
507 {
508 edgeLabel = 1;
509 CallDirSVFGEdge *attributedEdge = SVFUtil::dyn_cast<CallDirSVFGEdge>(edge);
510 CFGrammar::Attribute attr = attributedEdge->getCallSiteId();
513 cflGraph->addCFLEdge(cflGraph->getGNode(edge->getSrcID()), cflGraph->getGNode(edge->getDstID()), edgeLabel);
514 std::string label = kindToLabelMap[edgeLabel];
515 label.append("bar"); // for example Gep_i should be Gepbar_i, not Gep_ibar
518 }
519 // Get 'call' edge : CallIndVF
520 else if ( edge->getEdgeKind() == VFGEdge::CallIndVF )
521 {
522 edgeLabel = 1;
523 CallIndSVFGEdge *attributedEdge = SVFUtil::dyn_cast<CallIndSVFGEdge>(edge);
524 CFGrammar::Attribute attr = attributedEdge->getCallSiteId();
527 cflGraph->addCFLEdge(cflGraph->getGNode(edge->getSrcID()), cflGraph->getGNode(edge->getDstID()), edgeLabel);
528 std::string label = kindToLabelMap[edgeLabel];
529 label.append("bar"); // for example Gep_i should be Gepbar_i, not Gep_ibar
532 }
533 // Get 'ret' edge : RetDirVF
534 else if ( edge->getEdgeKind() == VFGEdge::RetDirVF )
535 {
536 edgeLabel = 2;
537 RetDirSVFGEdge *attributedEdge = SVFUtil::dyn_cast<RetDirSVFGEdge>(edge);
538 CFGrammar::Attribute attr = attributedEdge->getCallSiteId();
541 cflGraph->addCFLEdge(cflGraph->getGNode(edge->getSrcID()), cflGraph->getGNode(edge->getDstID()), edgeLabel);
542 std::string label = kindToLabelMap[edgeLabel];
543 label.append("bar"); // for example Gep_i should be Gepbar_i, not Gep_ibar
546 }
547 // Get 'ret' edge : RetIndVF
548 else if ( edge->getEdgeKind() == VFGEdge::RetIndVF )
549 {
550 edgeLabel = 2;
551 RetIndSVFGEdge *attributedEdge = SVFUtil::dyn_cast<RetIndSVFGEdge>(edge);
552 CFGrammar::Attribute attr = attributedEdge->getCallSiteId();
555 cflGraph->addCFLEdge(cflGraph->getGNode(edge->getSrcID()), cflGraph->getGNode(edge->getDstID()), edgeLabel);
556 std::string label = kindToLabelMap[edgeLabel];
557 label.append("bar"); // for example Gep_i should be Gepbar_i, not Gep_ibar
560 }
561 }
562 }
563 return cflGraph;
564}
565
567{
568 CFLGraph *cflGraph = new CFLGraph(startKind);
569 return cflGraph;
570}
571
572
573} // 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:57
Map< std::string, Kind > & getNonterminals()
Definition CFGrammar.h:164
Map< std::string, Kind > & getTerminals()
Definition CFGrammar.h:174
Kind getStartKind()
Definition CFGrammar.h:209
std::string kindToStr(Kind kind) const
static Kind getAttributedKind(Attribute attribute, Kind kind)
Definition CFGrammar.h:269
static bool isNullPtr(NodeID id)
Definition IRGraph.h:160
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:227
const BaseObjVar * getBaseObject(NodeID id) const
Definition SVFIR.h:498
NodeID addDummyValNode()
Definition SVFIR.h:566
NodeID getId() const
Get ID.
Definition SVFValue.h:160
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:82
std::ostream & errs()
Overwrite llvm::errs()
Definition SVFUtil.h:58
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:196
for isBitcode
Definition BasicTypes.h:70
u32_t NodeID
Definition GeneralType.h:76
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:76
unsigned u32_t
Definition GeneralType.h:67