Static Value-Flow Analysis
AndersenSFR.cpp
Go to the documentation of this file.
1 //===- AndersenSFR.cpp -- SFR based field-sensitive Andersen's analysis-------//
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  * AndersenSFR.cpp
25  *
26  * Created on: 09, Feb, 2019
27  * Author: Yuxiang Lei
28  */
29 
30 #include "WPA/AndersenPWC.h"
31 #include "MemoryModel/PointsTo.h"
32 
33 using namespace SVF;
34 using namespace SVFUtil;
35 using namespace std;
36 
38 
43 {
45  setDetectPWC(false); // SCC will detect only copy edges
46 
47  if (!csc)
48  csc = new CSC(_graph, scc.get());
49 
51  getSCCDetector()->find();
52  mergeSccCycle();
53 }
54 
55 
60 {
62  csc->find(getSCCDetector()->topoNodeStack());
63 }
64 
65 
70 {
71  ConstraintNode* node = consCG->getConstraintNode(nodeId);
72  if (!node->strides.empty())
73  {
74  ConstraintNode* newRepNode = consCG->getConstraintNode(newRepId);
75  newRepNode->strides |= node->strides;
76  }
77  return Andersen::mergeSrcToTgt(nodeId, newRepId);
78 }
79 
80 
84 bool AndersenSFR::processGepPts(const PointsTo& pts, const GepCGEdge* edge)
85 {
86  ConstraintNode* dst = edge->getDstNode();
87  NodeID dstId = dst->getId();
88 
89  if (!dst->strides.empty() && SVFUtil::isa<NormalGepCGEdge>(edge)) // dst is in pwc
90  {
91  PointsTo tmpDstPts;
92  PointsTo srcInits = pts - getPts(dstId);
93 
94  if (!srcInits.empty())
95  {
96  NodeSet sortSrcInits;
97  for (NodeID ptd : srcInits)
98  sortSrcInits.insert(ptd);
99 
100  APOffset offset = SVFUtil::dyn_cast<NormalGepCGEdge>(edge)->getConstantFieldIdx();
101  fieldExpand(sortSrcInits, offset, dst->strides, tmpDstPts);
102  }
103 
104  if (unionPts(dstId, tmpDstPts))
105  {
106  pushIntoWorklist(dstId);
107  return true;
108  }
109  else
110  return false;
111  }
112  else
113  return Andersen::processGepPts(pts, edge);
114 }
115 
116 
120 void AndersenSFR::fieldExpand(NodeSet& initials, APOffset offset, NodeBS& strides, PointsTo& expandPts)
121 {
122  numOfFieldExpand++;
123 
124  while (!initials.empty())
125  {
126  NodeID init = *initials.begin();
127  initials.erase(init);
128 
129  if (consCG->isBlkObjOrConstantObj(init))
130  expandPts.set(init);
131  else
132  {
133  PAGNode* initPN = pag->getGNode(init);
134  const MemObj* obj = pag->getBaseObj(init);
135  const u32_t maxLimit = obj->getMaxFieldOffsetLimit();
136  APOffset initOffset;
137  if (GepObjVar *gepNode = SVFUtil::dyn_cast<GepObjVar>(initPN))
138  initOffset = gepNode->getConstantFieldIdx();
139  else if (SVFUtil::isa<FIObjVar, DummyObjVar>(initPN))
140  initOffset = 0;
141  else
142  {
143  assert(false && "Not an object node!!");
144  abort();
145  }
146 
147  Set<APOffset> offsets;
148  offsets.insert(offset);
149 
150  // calculate offsets
151  bool loopFlag = true;
152  while (loopFlag)
153  {
154  loopFlag = false;
155  for (auto _f : offsets)
156  for (auto _s : strides)
157  {
158  APOffset _f1 = _f + _s;
159  loopFlag = (offsets.find(_f1) == offsets.end()) && ( (u32_t)(initOffset + _f1) < maxLimit);
160  if (loopFlag)
161  offsets.insert(_f1);
162  }
163  }
164 
165  // get gep objs
166  for (APOffset _f : offsets)
167  {
168  NodeID gepId = consCG->getGepObjVar(init, _f);
169  initials.erase(gepId); // gep id in initials should be removed to avoid redundant derivation
170  expandPts.set(gepId);
171  }
172  }
173  }
174 }
buffer offset
Definition: cJSON.cpp:1113
virtual void PWCDetect()
void initialize()
Initialize analysis.
Definition: AndersenSFR.cpp:42
bool processGepPts(const PointsTo &pts, const GepCGEdge *edge)
Definition: AndersenSFR.cpp:84
void fieldExpand(NodeSet &initials, APOffset offset, NodeBS &strides, PointsTo &expandPts)
static AndersenSFR * sfrAndersen
Definition: AndersenPWC.h:110
bool mergeSrcToTgt(NodeID nodeId, NodeID newRepId)
Definition: AndersenSFR.cpp:69
virtual void initialize()
Initialize analysis.
Definition: Andersen.cpp:418
virtual bool processGepPts(const PointsTo &pts, const GepCGEdge *edge)
Definition: Andersen.cpp:622
virtual bool mergeSrcToTgt(NodeID srcId, NodeID tgtId)
Definition: Andersen.cpp:858
Definition: CSC.h:50
NodeBS strides
For stride-based field representation.
Definition: ConsGNode.h:71
NodeType * getDstNode() const
Definition: GenericGraph.h:101
u32_t getMaxFieldOffsetLimit() const
Get max field offset limit.
bool empty() const
Returns true if set is empty.
Definition: PointsTo.cpp:98
void set(u32_t n)
Inserts n in the set.
Definition: PointsTo.cpp:157
NodeID getId() const
Get ID.
Definition: GenericGraph.h:260
for isBitcode
Definition: BasicTypes.h:68
Set< NodeID > NodeSet
Definition: GeneralType.h:113
u32_t NodeID
Definition: GeneralType.h:55
s64_t APOffset
Definition: GeneralType.h:60
unsigned u32_t
Definition: GeneralType.h:46
std::unordered_set< Key, Hash, KeyEqual, Allocator > Set
Definition: GeneralType.h:96