svf-tools 1.0.1199 → 1.0.1201
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "svf-tools",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1201",
|
|
4
4
|
"description": "* <b>[TypeClone](https://github.com/SVF-tools/SVF/wiki/TypeClone) published in our [ECOOP paper](https://yuleisui.github.io/publications/ecoop20.pdf) is now available in SVF </b> * <b>SVF now uses a single script for its build. Just type [`source ./build.sh`](https://github.com/SVF-tools/SVF/blob/master/build.sh) in your terminal, that's it!</b> * <b>SVF now supports LLVM-10.0.0! </b> * <b>We thank [bsauce](https://github.com/bsauce) for writing a user manual of SVF ([link1](https://www.jianshu.com/p/068a08ec749c) and [link2](https://www.jianshu.com/p/777c30d4240e)) in Chinese </b> * <b>SVF now supports LLVM-9.0.0 (Thank [Byoungyoung Lee](https://github.com/SVF-tools/SVF/issues/142) for his help!). </b> * <b>SVF now supports a set of [field-sensitive pointer analyses](https://yuleisui.github.io/publications/sas2019a.pdf). </b> * <b>[Use SVF as an external lib](https://github.com/SVF-tools/SVF/wiki/Using-SVF-as-a-lib-in-your-own-tool) for your own project (Contributed by [Hongxu Chen](https://github.com/HongxuChen)). </b> * <b>SVF now supports LLVM-7.0.0. </b> * <b>SVF now supports Docker. [Try SVF in Docker](https://github.com/SVF-tools/SVF/wiki/Try-SVF-in-Docker)! </b> * <b>SVF now supports [LLVM-6.0.0](https://github.com/svf-tools/SVF/pull/38) (Contributed by [Jack Anthony](https://github.com/jackanth)). </b> * <b>SVF now supports [LLVM-4.0.0](https://github.com/svf-tools/SVF/pull/23) (Contributed by Jared Carlson. Thank [Jared](https://github.com/jcarlson23) and [Will](https://github.com/dtzWill) for their in-depth [discussions](https://github.com/svf-tools/SVF/pull/18) about updating SVF!) </b> * <b>SVF now supports analysis for C++ programs.</b> <br />",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
#include "AE/Core/AbstractState.h"
|
|
33
33
|
#include "AE/Core/ICFGWTO.h"
|
|
34
34
|
#include "AE/Svfexe/AEDetector.h"
|
|
35
|
+
#include "AE/Svfexe/PreAnalysis.h"
|
|
35
36
|
#include "AE/Svfexe/AbsExtAPI.h"
|
|
36
37
|
#include "Util/SVFBugReport.h"
|
|
37
38
|
#include "Util/SVFStat.h"
|
|
@@ -111,8 +112,6 @@ class AbstractInterpretation
|
|
|
111
112
|
friend class NullptrDerefDetector;
|
|
112
113
|
|
|
113
114
|
public:
|
|
114
|
-
typedef SCCDetection<CallGraph*> CallGraphSCC;
|
|
115
|
-
|
|
116
115
|
/*
|
|
117
116
|
* For recursive test case
|
|
118
117
|
* int demo(int a) {
|
|
@@ -189,9 +188,6 @@ private:
|
|
|
189
188
|
/// Global ICFGNode is handled at the entry of the program,
|
|
190
189
|
virtual void handleGlobalNode();
|
|
191
190
|
|
|
192
|
-
/// Compute IWTO for each function partition entry
|
|
193
|
-
void initWTO();
|
|
194
|
-
|
|
195
191
|
/**
|
|
196
192
|
* Check if execution state exist by merging states of predecessor nodes
|
|
197
193
|
*
|
|
@@ -260,13 +256,6 @@ private:
|
|
|
260
256
|
*/
|
|
261
257
|
std::vector<const ICFGNode*> getNextNodesOfCycle(const ICFGCycleWTO* cycle) const;
|
|
262
258
|
|
|
263
|
-
/**
|
|
264
|
-
* Recursively collect cycle heads from nested WTO components
|
|
265
|
-
*
|
|
266
|
-
* @param comps The list of WTO components to collect cycle heads from
|
|
267
|
-
*/
|
|
268
|
-
void collectCycleHeads(const std::list<const ICFGWTOComp*>& comps);
|
|
269
|
-
|
|
270
259
|
/**
|
|
271
260
|
* handle SVF Statement like CmpStmt, CallStmt, GepStmt, LoadStmt, StoreStmt, etc.
|
|
272
261
|
*
|
|
@@ -333,10 +322,7 @@ private:
|
|
|
333
322
|
CallGraph* callGraph;
|
|
334
323
|
AEStat* stat;
|
|
335
324
|
|
|
336
|
-
|
|
337
|
-
Set<std::pair<const CallICFGNode*, NodeID>> nonRecursiveCallSites;
|
|
338
|
-
Set<const FunObjVar*> recursiveFuns;
|
|
339
|
-
Map<const ICFGNode*, const ICFGCycleWTO*> cycleHeadToCycle;
|
|
325
|
+
PreAnalysis* preAnalysis{nullptr};
|
|
340
326
|
|
|
341
327
|
|
|
342
328
|
bool hasAbsStateFromTrace(const ICFGNode* node)
|
|
@@ -353,8 +339,7 @@ private:
|
|
|
353
339
|
virtual bool isExtCall(const CallICFGNode* callNode);
|
|
354
340
|
virtual void handleExtCall(const CallICFGNode* callNode);
|
|
355
341
|
virtual bool isRecursiveFun(const FunObjVar* fun);
|
|
356
|
-
virtual
|
|
357
|
-
virtual void recursiveCallPass(const CallICFGNode *callNode);
|
|
342
|
+
virtual void handleRecursiveCall(const CallICFGNode *callNode);
|
|
358
343
|
virtual bool isRecursiveCallSite(const CallICFGNode* callNode, const FunObjVar *);
|
|
359
344
|
virtual void handleFunCall(const CallICFGNode* callNode);
|
|
360
345
|
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
//===- PreAnalysis.h -- Pre-Analysis for Abstract Interpretation----------//
|
|
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
|
+
* PreAnalysis.h
|
|
25
|
+
*
|
|
26
|
+
* Created on: Feb 25, 2026
|
|
27
|
+
* Author: Jiawei Wang
|
|
28
|
+
*
|
|
29
|
+
* This file provides a pre-analysis phase for Abstract Interpretation.
|
|
30
|
+
* It runs Andersen's pointer analysis and builds WTO (Weak Topological Order)
|
|
31
|
+
* for each function before the main abstract interpretation.
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
#ifndef INCLUDE_AE_SVFEXE_PREANALYSIS_H_
|
|
35
|
+
#define INCLUDE_AE_SVFEXE_PREANALYSIS_H_
|
|
36
|
+
|
|
37
|
+
#include "SVFIR/SVFIR.h"
|
|
38
|
+
#include "Graphs/ICFG.h"
|
|
39
|
+
#include "Graphs/CallGraph.h"
|
|
40
|
+
#include "Graphs/SCC.h"
|
|
41
|
+
#include "AE/Core/ICFGWTO.h"
|
|
42
|
+
#include "WPA/Andersen.h"
|
|
43
|
+
|
|
44
|
+
namespace SVF
|
|
45
|
+
{
|
|
46
|
+
|
|
47
|
+
class PreAnalysis
|
|
48
|
+
{
|
|
49
|
+
public:
|
|
50
|
+
typedef SCCDetection<CallGraph*> CallGraphSCC;
|
|
51
|
+
|
|
52
|
+
PreAnalysis(SVFIR* pag, ICFG* icfg);
|
|
53
|
+
virtual ~PreAnalysis();
|
|
54
|
+
|
|
55
|
+
/// Accessors for Andersen's results
|
|
56
|
+
AndersenWaveDiff* getPointerAnalysis() const { return pta; }
|
|
57
|
+
CallGraph* getCallGraph() const { return callGraph; }
|
|
58
|
+
CallGraphSCC* getCallGraphSCC() const { return callGraphSCC; }
|
|
59
|
+
|
|
60
|
+
/// Build WTO for each function using call graph SCC
|
|
61
|
+
void initWTO();
|
|
62
|
+
|
|
63
|
+
/// Accessors for WTO data
|
|
64
|
+
const Map<const FunObjVar*, const ICFGWTO*>& getFuncToWTO() const
|
|
65
|
+
{
|
|
66
|
+
return funcToWTO;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
private:
|
|
70
|
+
SVFIR* svfir;
|
|
71
|
+
ICFG* icfg;
|
|
72
|
+
AndersenWaveDiff* pta;
|
|
73
|
+
CallGraph* callGraph;
|
|
74
|
+
CallGraphSCC* callGraphSCC;
|
|
75
|
+
|
|
76
|
+
Map<const FunObjVar*, const ICFGWTO*> funcToWTO;
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
} // End namespace SVF
|
|
80
|
+
|
|
81
|
+
#endif /* INCLUDE_AE_SVFEXE_PREANALYSIS_H_ */
|
|
@@ -48,6 +48,12 @@ void AbstractInterpretation::runOnModule(ICFG *_icfg)
|
|
|
48
48
|
svfir = PAG::getPAG();
|
|
49
49
|
utils = new AbsExtAPI(abstractTrace);
|
|
50
50
|
|
|
51
|
+
// Run Andersen's pointer analysis and build WTO
|
|
52
|
+
preAnalysis = new PreAnalysis(svfir, icfg);
|
|
53
|
+
callGraph = preAnalysis->getCallGraph();
|
|
54
|
+
icfg->updateCallGraph(callGraph);
|
|
55
|
+
preAnalysis->initWTO();
|
|
56
|
+
|
|
51
57
|
/// collect checkpoint
|
|
52
58
|
collectCheckPoint();
|
|
53
59
|
|
|
@@ -63,103 +69,13 @@ void AbstractInterpretation::runOnModule(ICFG *_icfg)
|
|
|
63
69
|
|
|
64
70
|
AbstractInterpretation::AbstractInterpretation()
|
|
65
71
|
{
|
|
66
|
-
AndersenWaveDiff* ander = AndersenWaveDiff::createAndersenWaveDiff(svfir);
|
|
67
|
-
callGraph = ander->getCallGraph();
|
|
68
72
|
stat = new AEStat(this);
|
|
69
73
|
}
|
|
70
74
|
/// Destructor
|
|
71
75
|
AbstractInterpretation::~AbstractInterpretation()
|
|
72
76
|
{
|
|
73
77
|
delete stat;
|
|
74
|
-
|
|
75
|
-
delete it.second;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* @brief Recursively collect cycle heads from nested WTO components
|
|
80
|
-
*
|
|
81
|
-
* This helper function traverses the WTO component tree and builds the cycleHeadToCycle
|
|
82
|
-
* map, which maps each cycle head node to its corresponding ICFGCycleWTO object.
|
|
83
|
-
* This enables efficient O(1) lookup of cycles during analysis.
|
|
84
|
-
*/
|
|
85
|
-
void AbstractInterpretation::collectCycleHeads(const std::list<const ICFGWTOComp*>& comps)
|
|
86
|
-
{
|
|
87
|
-
for (const ICFGWTOComp* comp : comps)
|
|
88
|
-
{
|
|
89
|
-
if (const ICFGCycleWTO* cycle = SVFUtil::dyn_cast<ICFGCycleWTO>(comp))
|
|
90
|
-
{
|
|
91
|
-
cycleHeadToCycle[cycle->head()->getICFGNode()] = cycle;
|
|
92
|
-
// Recursively collect nested cycle heads
|
|
93
|
-
collectCycleHeads(cycle->getWTOComponents());
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
void AbstractInterpretation::initWTO()
|
|
99
|
-
{
|
|
100
|
-
AndersenWaveDiff* ander = AndersenWaveDiff::createAndersenWaveDiff(svfir);
|
|
101
|
-
CallGraphSCC* callGraphScc = ander->getCallGraphSCC();
|
|
102
|
-
callGraphScc->find();
|
|
103
|
-
// Iterate through the call graph
|
|
104
|
-
for (auto it = callGraph->begin(); it != callGraph->end(); it++)
|
|
105
|
-
{
|
|
106
|
-
// Check if the current function is part of a cycle
|
|
107
|
-
if (callGraphScc->isInCycle(it->second->getId()))
|
|
108
|
-
recursiveFuns.insert(it->second->getFunction()); // Mark the function as recursive
|
|
109
|
-
|
|
110
|
-
// Calculate ICFGWTO for each function/recursion
|
|
111
|
-
const FunObjVar *fun = it->second->getFunction();
|
|
112
|
-
if (fun->isDeclaration())
|
|
113
|
-
continue;
|
|
114
|
-
|
|
115
|
-
NodeID repNodeId = callGraphScc->repNode(it->second->getId());
|
|
116
|
-
auto cgSCCNodes = callGraphScc->subNodes(repNodeId);
|
|
117
|
-
|
|
118
|
-
// Identify if this node is an SCC entry (nodes who have incoming edges
|
|
119
|
-
// from nodes outside the SCC). Also identify non-recursive callsites.
|
|
120
|
-
bool isEntry = false;
|
|
121
|
-
if (it->second->getInEdges().empty())
|
|
122
|
-
isEntry = true;
|
|
123
|
-
for (auto inEdge: it->second->getInEdges())
|
|
124
|
-
{
|
|
125
|
-
NodeID srcNodeId = inEdge->getSrcID();
|
|
126
|
-
if (!cgSCCNodes.test(srcNodeId))
|
|
127
|
-
{
|
|
128
|
-
isEntry = true;
|
|
129
|
-
const CallICFGNode *callSite = nullptr;
|
|
130
|
-
if (inEdge->isDirectCallEdge())
|
|
131
|
-
callSite = *(inEdge->getDirectCalls().begin());
|
|
132
|
-
else if (inEdge->isIndirectCallEdge())
|
|
133
|
-
callSite = *(inEdge->getIndirectCalls().begin());
|
|
134
|
-
else
|
|
135
|
-
assert(false && "CallGraphEdge must "
|
|
136
|
-
"be either direct or indirect!");
|
|
137
|
-
|
|
138
|
-
nonRecursiveCallSites.insert(
|
|
139
|
-
{callSite, inEdge->getDstNode()->getFunction()->getId()});
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
// Compute IWTO for the function partition entered from each partition entry
|
|
144
|
-
if (isEntry)
|
|
145
|
-
{
|
|
146
|
-
Set<const FunObjVar*> funcScc;
|
|
147
|
-
for (const auto& node: cgSCCNodes)
|
|
148
|
-
{
|
|
149
|
-
funcScc.insert(callGraph->getGNode(node)->getFunction());
|
|
150
|
-
}
|
|
151
|
-
ICFGWTO* iwto = new ICFGWTO(icfg->getFunEntryICFGNode(fun), funcScc);
|
|
152
|
-
iwto->init();
|
|
153
|
-
funcToWTO[it->second->getFunction()] = iwto;
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
// Build cycleHeadToCycle map for all functions
|
|
158
|
-
// This maps cycle head nodes to their corresponding WTO cycles for efficient lookup
|
|
159
|
-
for (auto& [func, wto] : funcToWTO)
|
|
160
|
-
{
|
|
161
|
-
collectCycleHeads(wto->getWTOComponents());
|
|
162
|
-
}
|
|
78
|
+
delete preAnalysis;
|
|
163
79
|
}
|
|
164
80
|
|
|
165
81
|
/// Collect entry point functions for analysis.
|
|
@@ -200,8 +116,6 @@ std::deque<const FunObjVar*> AbstractInterpretation::collectProgEntryFuns()
|
|
|
200
116
|
/// Program entry - analyze from all entry points (multi-entry analysis is the default)
|
|
201
117
|
void AbstractInterpretation::analyse()
|
|
202
118
|
{
|
|
203
|
-
initWTO();
|
|
204
|
-
|
|
205
119
|
// Always use multi-entry analysis from all entry points
|
|
206
120
|
analyzeFromAllProgEntries();
|
|
207
121
|
}
|
|
@@ -814,8 +728,8 @@ std::vector<const ICFGNode*> AbstractInterpretation::getNextNodesOfCycle(const I
|
|
|
814
728
|
*/
|
|
815
729
|
void AbstractInterpretation::handleFunction(const ICFGNode* funEntry, const CallICFGNode* caller)
|
|
816
730
|
{
|
|
817
|
-
auto it =
|
|
818
|
-
if (it ==
|
|
731
|
+
auto it = preAnalysis->getFuncToWTO().find(funEntry->getFun());
|
|
732
|
+
if (it == preAnalysis->getFuncToWTO().end())
|
|
819
733
|
return;
|
|
820
734
|
|
|
821
735
|
// Push all top-level WTO components into the worklist in WTO order
|
|
@@ -872,21 +786,11 @@ void AbstractInterpretation::handleExtCall(const CallICFGNode *callNode)
|
|
|
872
786
|
/// Check if a function is recursive (part of a call graph SCC)
|
|
873
787
|
bool AbstractInterpretation::isRecursiveFun(const FunObjVar* fun)
|
|
874
788
|
{
|
|
875
|
-
return
|
|
876
|
-
}
|
|
877
|
-
|
|
878
|
-
/// Check if a call node calls a recursive function
|
|
879
|
-
bool AbstractInterpretation::isRecursiveCall(const CallICFGNode *callNode)
|
|
880
|
-
{
|
|
881
|
-
const FunObjVar *callfun = callNode->getCalledFunction();
|
|
882
|
-
if (!callfun)
|
|
883
|
-
return false;
|
|
884
|
-
else
|
|
885
|
-
return isRecursiveFun(callfun);
|
|
789
|
+
return preAnalysis->getPointerAnalysis()->isInRecursion(fun);
|
|
886
790
|
}
|
|
887
791
|
|
|
888
792
|
/// Handle recursive call in TOP mode: set all stores and return value to TOP
|
|
889
|
-
void AbstractInterpretation::
|
|
793
|
+
void AbstractInterpretation::handleRecursiveCall(const CallICFGNode *callNode)
|
|
890
794
|
{
|
|
891
795
|
AbstractState& as = getAbsStateFromTrace(callNode);
|
|
892
796
|
setTopToObjInRecursion(callNode);
|
|
@@ -905,12 +809,12 @@ void AbstractInterpretation::recursiveCallPass(const CallICFGNode *callNode)
|
|
|
905
809
|
abstractTrace[retNode] = as;
|
|
906
810
|
}
|
|
907
811
|
|
|
908
|
-
/// Check if
|
|
812
|
+
/// Check if caller and callee are in the same CallGraph SCC (i.e. a recursive callsite)
|
|
909
813
|
bool AbstractInterpretation::isRecursiveCallSite(const CallICFGNode* callNode,
|
|
910
814
|
const FunObjVar* callee)
|
|
911
815
|
{
|
|
912
|
-
|
|
913
|
-
|
|
816
|
+
const FunObjVar* caller = callNode->getCaller();
|
|
817
|
+
return preAnalysis->getPointerAnalysis()->inSameCallGraphSCC(caller, callee);
|
|
914
818
|
}
|
|
915
819
|
|
|
916
820
|
/// Get callee function: directly for direct calls, via pointer analysis for indirect calls
|
|
@@ -1013,7 +917,7 @@ void AbstractInterpretation::handleFunCall(const CallICFGNode *callNode)
|
|
|
1013
917
|
}
|
|
1014
918
|
|
|
1015
919
|
// Indirect call: use Andersen's call graph to get all resolved callees.
|
|
1016
|
-
// The call graph was built during initWTO() by running Andersen's pointer analysis,
|
|
920
|
+
// The call graph was built during PreAnalysis::initWTO() by running Andersen's pointer analysis,
|
|
1017
921
|
// which over-approximates the set of possible targets for each indirect callsite.
|
|
1018
922
|
if (callGraph->hasIndCSCallees(callNode))
|
|
1019
923
|
{
|
|
@@ -1051,7 +955,7 @@ void AbstractInterpretation::handleFunCall(const CallICFGNode *callNode)
|
|
|
1051
955
|
/// Behavior depends on Options::HandleRecur():
|
|
1052
956
|
///
|
|
1053
957
|
/// - TOP mode:
|
|
1054
|
-
/// Does not iterate. Calls
|
|
958
|
+
/// Does not iterate. Calls handleRecursiveCall() to set all stores and
|
|
1055
959
|
/// return value to TOP immediately. This is the most conservative but fastest.
|
|
1056
960
|
/// Example:
|
|
1057
961
|
/// int factorial(int n) { return n <= 1 ? 1 : n * factorial(n-1); }
|
|
@@ -1074,13 +978,13 @@ void AbstractInterpretation::handleLoopOrRecursion(const ICFGCycleWTO* cycle, co
|
|
|
1074
978
|
{
|
|
1075
979
|
const ICFGNode* cycle_head = cycle->head()->getICFGNode();
|
|
1076
980
|
|
|
1077
|
-
// TOP mode for recursive function cycles: use
|
|
981
|
+
// TOP mode for recursive function cycles: use handleRecursiveCall to set
|
|
1078
982
|
// all stores and return value to TOP, maintaining original semantics
|
|
1079
983
|
if (Options::HandleRecur() == TOP && isRecursiveFun(cycle_head->getFun()))
|
|
1080
984
|
{
|
|
1081
985
|
if (caller)
|
|
1082
986
|
{
|
|
1083
|
-
|
|
987
|
+
handleRecursiveCall(caller);
|
|
1084
988
|
}
|
|
1085
989
|
return;
|
|
1086
990
|
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
//===- PreAnalysis.cpp -- Pre-Analysis for Abstract Interpretation---------//
|
|
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
|
+
* PreAnalysis.cpp
|
|
25
|
+
*
|
|
26
|
+
* Created on: Feb 25, 2026
|
|
27
|
+
* Author: Jiawei Wang
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
#include "AE/Svfexe/PreAnalysis.h"
|
|
31
|
+
|
|
32
|
+
using namespace SVF;
|
|
33
|
+
|
|
34
|
+
PreAnalysis::PreAnalysis(SVFIR* pag, ICFG* icfg)
|
|
35
|
+
: svfir(pag), icfg(icfg)
|
|
36
|
+
{
|
|
37
|
+
pta = AndersenWaveDiff::createAndersenWaveDiff(svfir);
|
|
38
|
+
callGraph = pta->getCallGraph();
|
|
39
|
+
callGraphSCC = pta->getCallGraphSCC();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
PreAnalysis::~PreAnalysis()
|
|
43
|
+
{
|
|
44
|
+
for (auto& [func, wto] : funcToWTO)
|
|
45
|
+
delete wto;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
void PreAnalysis::initWTO()
|
|
49
|
+
{
|
|
50
|
+
callGraphSCC->find();
|
|
51
|
+
|
|
52
|
+
for (auto it = callGraph->begin(); it != callGraph->end(); it++)
|
|
53
|
+
{
|
|
54
|
+
const FunObjVar *fun = it->second->getFunction();
|
|
55
|
+
if (fun->isDeclaration())
|
|
56
|
+
continue;
|
|
57
|
+
|
|
58
|
+
NodeID repNodeId = callGraphSCC->repNode(it->second->getId());
|
|
59
|
+
auto cgSCCNodes = callGraphSCC->subNodes(repNodeId);
|
|
60
|
+
|
|
61
|
+
bool isEntry = false;
|
|
62
|
+
if (it->second->getInEdges().empty())
|
|
63
|
+
isEntry = true;
|
|
64
|
+
for (auto inEdge: it->second->getInEdges())
|
|
65
|
+
{
|
|
66
|
+
NodeID srcNodeId = inEdge->getSrcID();
|
|
67
|
+
if (!cgSCCNodes.test(srcNodeId))
|
|
68
|
+
isEntry = true;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (isEntry)
|
|
72
|
+
{
|
|
73
|
+
Set<const FunObjVar*> funcScc;
|
|
74
|
+
for (const auto& node: cgSCCNodes)
|
|
75
|
+
{
|
|
76
|
+
funcScc.insert(callGraph->getGNode(node)->getFunction());
|
|
77
|
+
}
|
|
78
|
+
ICFGWTO* iwto = new ICFGWTO(icfg->getFunEntryICFGNode(fun), funcScc);
|
|
79
|
+
iwto->init();
|
|
80
|
+
funcToWTO[it->second->getFunction()] = iwto;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
}
|
package/svf-llvm/tools/AE/ae.cpp
CHANGED
|
@@ -878,10 +878,10 @@ int main(int argc, char** argv)
|
|
|
878
878
|
LLVMModuleSet::getLLVMModuleSet()->buildSVFModule(moduleNameVec);
|
|
879
879
|
SVFIRBuilder builder;
|
|
880
880
|
SVFIR* pag = builder.build();
|
|
881
|
+
// Run Andersen's to resolve indirect calls, then update SVFIR with resolved targets.
|
|
882
|
+
// The Andersen singleton will be reused inside AbstractInterpretation::runOnModule().
|
|
881
883
|
AndersenWaveDiff* ander = AndersenWaveDiff::createAndersenWaveDiff(pag);
|
|
882
|
-
|
|
883
|
-
builder.updateCallGraph(callgraph);
|
|
884
|
-
pag->getICFG()->updateCallGraph(callgraph);
|
|
884
|
+
builder.updateCallGraph(ander->getCallGraph());
|
|
885
885
|
AbstractInterpretation& ae = AbstractInterpretation::getAEInstance();
|
|
886
886
|
if (Options::BufferOverflowCheck())
|
|
887
887
|
ae.addDetector(std::make_unique<BufOverflowDetector>());
|