svf-tools 1.0.418 → 1.0.421
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/SVF-doxygen/html/html/AndersenWaveDiff_8cpp_source.html +1 -1
- package/SVF-doxygen/html/html/Andersen_8cpp_source.html +14 -14
- package/SVF-doxygen/html/html/CHGBuilder_8cpp_source.html +1 -1
- package/SVF-doxygen/html/html/Conditions_8cpp.html +0 -1
- package/SVF-doxygen/html/html/Conditions_8cpp_source.html +58 -49
- package/SVF-doxygen/html/html/Conditions_8h.html +6 -2
- package/SVF-doxygen/html/html/Conditions_8h_source.html +68 -60
- package/SVF-doxygen/html/html/ConsG_8cpp_source.html +2 -2
- package/SVF-doxygen/html/html/ContextDDA_8cpp_source.html +1 -1
- package/SVF-doxygen/html/html/DCHG_8cpp_source.html +1 -1
- package/SVF-doxygen/html/html/DDAPass_8cpp_source.html +9 -9
- package/SVF-doxygen/html/html/FSMPTA_8cpp_source.html +3 -3
- package/SVF-doxygen/html/html/FlowSensitiveTBHC_8cpp_source.html +2 -2
- package/SVF-doxygen/html/html/FlowSensitive_8cpp_source.html +7 -7
- package/SVF-doxygen/html/html/ICFG_8cpp_source.html +1 -1
- package/SVF-doxygen/html/html/IRGraph_8cpp_source.html +1 -1
- package/SVF-doxygen/html/html/LeakChecker_8cpp_source.html +1 -1
- package/SVF-doxygen/html/html/LockAnalysis_8cpp_source.html +1 -1
- package/SVF-doxygen/html/html/LockResultValidator_8cpp_source.html +1 -1
- package/SVF-doxygen/html/html/MHP_8cpp_source.html +1 -1
- package/SVF-doxygen/html/html/MTAAnnotator_8cpp_source.html +1 -1
- package/SVF-doxygen/html/html/MTAResultValidator_8cpp_source.html +1 -1
- package/SVF-doxygen/html/html/MTAStat_8cpp_source.html +1 -1
- package/SVF-doxygen/html/html/MemRegion_8cpp_source.html +1 -1
- package/SVF-doxygen/html/html/MemSSA_8cpp_source.html +2 -2
- package/SVF-doxygen/html/html/NodeIDAllocator_8cpp_source.html +6 -6
- package/SVF-doxygen/html/html/OfflineConsG_8cpp_source.html +1 -1
- package/SVF-doxygen/html/html/Options_8cpp_source.html +114 -113
- package/SVF-doxygen/html/html/Options_8h.html +1 -0
- package/SVF-doxygen/html/html/Options_8h_source.html +117 -115
- package/SVF-doxygen/html/html/PTAStat_8cpp_source.html +2 -2
- package/SVF-doxygen/html/html/PathCondAllocator_8cpp_source.html +41 -23
- package/SVF-doxygen/html/html/PathCondAllocator_8h_source.html +74 -74
- package/SVF-doxygen/html/html/PathDPItem_8h_source.html +7 -7
- package/SVF-doxygen/html/html/PointerAnalysisImpl_8cpp_source.html +4 -4
- package/SVF-doxygen/html/html/PointerAnalysis_8cpp_source.html +12 -12
- package/SVF-doxygen/html/html/PointsTo_8cpp_source.html +1 -1
- package/SVF-doxygen/html/html/ProgSlice_8cpp_source.html +1 -1
- package/SVF-doxygen/html/html/ProgSlice_8h_source.html +13 -13
- package/SVF-doxygen/html/html/SVFGBuilder_8cpp_source.html +5 -5
- package/SVF-doxygen/html/html/SVFGOPT_8cpp_source.html +4 -4
- package/SVF-doxygen/html/html/SVFG_8cpp_source.html +1 -1
- package/SVF-doxygen/html/html/SVFIR_8cpp_source.html +3 -3
- package/SVF-doxygen/html/html/SVFStatements_8cpp_source.html +1 -1
- package/SVF-doxygen/html/html/SVFUtil_8cpp_source.html +1 -1
- package/SVF-doxygen/html/html/SVFVariables_8cpp_source.html +1 -1
- package/SVF-doxygen/html/html/SrcSnkDDA_8cpp_source.html +4 -4
- package/SVF-doxygen/html/html/SymbolTableBuilder_8cpp_source.html +3 -3
- package/SVF-doxygen/html/html/SymbolTableInfo_8cpp_source.html +3 -3
- package/SVF-doxygen/html/html/TCT_8cpp_source.html +1 -1
- package/SVF-doxygen/html/html/TypeAnalysis_8cpp_source.html +1 -1
- package/SVF-doxygen/html/html/VFG_8cpp_source.html +1 -1
- package/SVF-doxygen/html/html/VersionedFlowSensitive_8cpp_source.html +3 -3
- package/SVF-doxygen/html/html/WPAPass_8cpp_source.html +4 -4
- package/SVF-doxygen/html/html/annotated.html +7 -5
- package/SVF-doxygen/html/html/classSVF_1_1AddrStmt.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1Andersen.html +23 -25
- package/SVF-doxygen/html/html/classSVF_1_1AndersenBase.html +6 -6
- package/SVF-doxygen/html/html/classSVF_1_1AndersenHCD.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1AndersenLCD.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1AndersenSFR.html +4 -0
- package/SVF-doxygen/html/html/classSVF_1_1AndersenWaveDiff.html +2 -6
- package/SVF-doxygen/html/html/classSVF_1_1BDDExpr-members.html +92 -0
- package/SVF-doxygen/html/html/classSVF_1_1BDDExpr.html +304 -0
- package/SVF-doxygen/html/html/classSVF_1_1BDDExpr.png +0 -0
- package/SVF-doxygen/html/html/classSVF_1_1BDDManager-members.html +124 -0
- package/SVF-doxygen/html/html/classSVF_1_1BDDManager.html +1139 -0
- package/SVF-doxygen/html/html/classSVF_1_1BDDManager.png +0 -0
- package/SVF-doxygen/html/html/classSVF_1_1BVDataPTAImpl.html +5 -5
- package/SVF-doxygen/html/html/classSVF_1_1BinaryOPStmt.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1BranchStmt.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1CHGBuilder.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1CallPE.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1CmpStmt.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1CondExpr-members.html +5 -8
- package/SVF-doxygen/html/html/classSVF_1_1CondExpr.html +22 -151
- package/SVF-doxygen/html/html/classSVF_1_1CondExpr.png +0 -0
- package/SVF-doxygen/html/html/classSVF_1_1CondManager-members.html +25 -36
- package/SVF-doxygen/html/html/classSVF_1_1CondManager.html +276 -605
- package/SVF-doxygen/html/html/classSVF_1_1CondManager.png +0 -0
- package/SVF-doxygen/html/html/classSVF_1_1ContextDDA.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1CopyStmt.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1DCHGraph.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1DDAPass.html +9 -9
- package/SVF-doxygen/html/html/classSVF_1_1FIObjVar.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1FlowDDA.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1FlowSensitive.html +9 -9
- package/SVF-doxygen/html/html/classSVF_1_1FlowSensitiveTBHC.html +7 -7
- package/SVF-doxygen/html/html/classSVF_1_1GepObjVar.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1GepStmt.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1GepValVar.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1ICFG.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1LLVMModuleSet.html +2 -2
- package/SVF-doxygen/html/html/classSVF_1_1LeakChecker.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1LoadStmt.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1LockAnalysis.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1LockResultValidator.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1MHP.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1MRGenerator.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1MTAAnnotator.html +4 -4
- package/SVF-doxygen/html/html/classSVF_1_1MTAResultValidator.html +3 -3
- package/SVF-doxygen/html/html/classSVF_1_1MTASVFGBuilder.html +6 -6
- package/SVF-doxygen/html/html/classSVF_1_1MTAStat.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1MemSSA.html +2 -2
- package/SVF-doxygen/html/html/classSVF_1_1NodeIDAllocator.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1NodeIDAllocator_1_1Clusterer.html +6 -6
- package/SVF-doxygen/html/html/classSVF_1_1ObjVar.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1OfflineConsG.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1Options-members.html +103 -102
- package/SVF-doxygen/html/html/classSVF_1_1Options.html +141 -115
- package/SVF-doxygen/html/html/classSVF_1_1PTAStat.html +3 -3
- package/SVF-doxygen/html/html/classSVF_1_1PathCondAllocator-members.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1PathCondAllocator.html +189 -196
- package/SVF-doxygen/html/html/classSVF_1_1PhiStmt.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1PointerAnalysis.html +13 -13
- package/SVF-doxygen/html/html/classSVF_1_1PointsTo.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1ProgSlice.html +20 -20
- package/SVF-doxygen/html/html/classSVF_1_1RetPE.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1SVFGBuilder.html +5 -5
- package/SVF-doxygen/html/html/classSVF_1_1SVFGOPT.html +5 -5
- package/SVF-doxygen/html/html/classSVF_1_1SVFIR.html +4 -4
- package/SVF-doxygen/html/html/classSVF_1_1SVFIRBuilder.html +5 -5
- package/SVF-doxygen/html/html/classSVF_1_1SelectStmt.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1SrcSnkDDA.html +8 -8
- package/SVF-doxygen/html/html/classSVF_1_1StoreStmt.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1SymbolTableBuilder.html +3 -3
- package/SVF-doxygen/html/html/classSVF_1_1SymbolTableInfo.html +5 -5
- package/SVF-doxygen/html/html/classSVF_1_1TCT.html +2 -2
- package/SVF-doxygen/html/html/classSVF_1_1TDForkPE.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1TDJoinPE.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1TypeAnalysis.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1UnaryOPStmt.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1VFG.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1ValVar.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1VersionedFlowSensitive.html +3 -3
- package/SVF-doxygen/html/html/classSVF_1_1WPAPass.html +11 -11
- package/SVF-doxygen/html/html/classSVF_1_1Z3Expr-members.html +95 -0
- package/SVF-doxygen/html/html/classSVF_1_1Z3Expr.html +396 -0
- package/SVF-doxygen/html/html/classSVF_1_1Z3Expr.png +0 -0
- package/SVF-doxygen/html/html/classSVF_1_1Z3Manager-members.html +122 -0
- package/SVF-doxygen/html/html/classSVF_1_1Z3Manager.html +1066 -0
- package/SVF-doxygen/html/html/classSVF_1_1Z3Manager.png +0 -0
- package/SVF-doxygen/html/html/classes.html +12 -11
- package/SVF-doxygen/html/html/functions_0x7e.html +9 -3
- package/SVF-doxygen/html/html/functions_a.html +4 -6
- package/SVF-doxygen/html/html/functions_b.html +33 -34
- package/SVF-doxygen/html/html/functions_c.html +43 -32
- package/SVF-doxygen/html/html/functions_d.html +5 -4
- package/SVF-doxygen/html/html/functions_e.html +8 -7
- package/SVF-doxygen/html/html/functions_enum.html +3 -0
- package/SVF-doxygen/html/html/functions_eval_b.html +6 -3
- package/SVF-doxygen/html/html/functions_eval_z.html +79 -0
- package/SVF-doxygen/html/html/functions_f.html +3 -3
- package/SVF-doxygen/html/html/functions_func.html +8 -7
- package/SVF-doxygen/html/html/functions_func_0x7e.html +9 -3
- package/SVF-doxygen/html/html/functions_func_b.html +10 -10
- package/SVF-doxygen/html/html/functions_func_c.html +23 -20
- package/SVF-doxygen/html/html/functions_func_d.html +5 -4
- package/SVF-doxygen/html/html/functions_func_e.html +3 -2
- package/SVF-doxygen/html/html/functions_func_g.html +33 -24
- package/SVF-doxygen/html/html/functions_func_i.html +17 -11
- package/SVF-doxygen/html/html/functions_func_n.html +4 -3
- package/SVF-doxygen/html/html/functions_func_o.html +4 -3
- package/SVF-doxygen/html/html/functions_func_p.html +3 -3
- package/SVF-doxygen/html/html/functions_func_s.html +2 -2
- package/SVF-doxygen/html/html/functions_func_z.html +79 -0
- package/SVF-doxygen/html/html/functions_g.html +35 -26
- package/SVF-doxygen/html/html/functions_i.html +30 -15
- package/SVF-doxygen/html/html/functions_l.html +8 -8
- package/SVF-doxygen/html/html/functions_m.html +1 -1
- package/SVF-doxygen/html/html/functions_n.html +4 -3
- package/SVF-doxygen/html/html/functions_o.html +9 -14
- package/SVF-doxygen/html/html/functions_p.html +10 -10
- package/SVF-doxygen/html/html/functions_r.html +7 -7
- package/SVF-doxygen/html/html/functions_rela.html +4 -0
- package/SVF-doxygen/html/html/functions_s.html +13 -15
- package/SVF-doxygen/html/html/functions_t.html +1 -3
- package/SVF-doxygen/html/html/functions_type_b.html +5 -6
- package/SVF-doxygen/html/html/functions_type_c.html +1 -1
- package/SVF-doxygen/html/html/functions_type_i.html +4 -1
- package/SVF-doxygen/html/html/functions_type_z.html +77 -0
- package/SVF-doxygen/html/html/functions_v.html +3 -3
- package/SVF-doxygen/html/html/functions_vars_a.html +0 -3
- package/SVF-doxygen/html/html/functions_vars_b.html +6 -9
- package/SVF-doxygen/html/html/functions_vars_c.html +5 -2
- package/SVF-doxygen/html/html/functions_vars_e.html +1 -1
- package/SVF-doxygen/html/html/functions_vars_i.html +6 -0
- package/SVF-doxygen/html/html/functions_vars_m.html +1 -1
- package/SVF-doxygen/html/html/functions_vars_n.html +1 -1
- package/SVF-doxygen/html/html/functions_vars_s.html +1 -1
- package/SVF-doxygen/html/html/functions_z.html +16 -0
- package/SVF-doxygen/html/html/hierarchy.html +436 -434
- package/SVF-doxygen/html/html/menudata.js +5 -2
- package/SVF-doxygen/html/html/namespaceSVF.html +8 -4
- package/SVF-doxygen/html/html/search/all_1.js +1 -2
- package/SVF-doxygen/html/html/search/all_10.js +11 -11
- package/SVF-doxygen/html/html/search/all_12.js +1 -1
- package/SVF-doxygen/html/html/search/all_13.js +8 -8
- package/SVF-doxygen/html/html/search/all_14.js +1 -1
- package/SVF-doxygen/html/html/search/all_15.js +1 -1
- package/SVF-doxygen/html/html/search/all_16.js +1 -1
- package/SVF-doxygen/html/html/search/all_1a.js +5 -0
- package/SVF-doxygen/html/html/search/all_1b.js +5 -3
- package/SVF-doxygen/html/html/search/all_2.js +10 -9
- package/SVF-doxygen/html/html/search/all_3.js +9 -7
- package/SVF-doxygen/html/html/search/all_4.js +3 -3
- package/SVF-doxygen/html/html/search/all_5.js +2 -2
- package/SVF-doxygen/html/html/search/all_6.js +1 -1
- package/SVF-doxygen/html/html/search/all_7.js +13 -11
- package/SVF-doxygen/html/html/search/all_9.js +8 -6
- package/SVF-doxygen/html/html/search/all_c.js +5 -5
- package/SVF-doxygen/html/html/search/all_d.js +2 -2
- package/SVF-doxygen/html/html/search/all_e.js +4 -4
- package/SVF-doxygen/html/html/search/all_f.js +2 -2
- package/SVF-doxygen/html/html/search/classes_1.js +2 -2
- package/SVF-doxygen/html/html/search/classes_14.html +26 -0
- package/SVF-doxygen/html/html/search/classes_14.js +5 -0
- package/SVF-doxygen/html/html/search/enums_1.js +1 -0
- package/SVF-doxygen/html/html/search/enumvalues_1.js +2 -1
- package/SVF-doxygen/html/html/search/enumvalues_14.html +26 -0
- package/SVF-doxygen/html/html/search/enumvalues_14.js +5 -0
- package/SVF-doxygen/html/html/search/functions_0.js +1 -1
- package/SVF-doxygen/html/html/search/functions_1.js +5 -5
- package/SVF-doxygen/html/html/search/functions_10.js +2 -2
- package/SVF-doxygen/html/html/search/functions_15.js +2 -0
- package/SVF-doxygen/html/html/search/functions_16.js +5 -3
- package/SVF-doxygen/html/html/search/functions_2.js +5 -5
- package/SVF-doxygen/html/html/search/functions_3.js +3 -3
- package/SVF-doxygen/html/html/search/functions_4.js +1 -1
- package/SVF-doxygen/html/html/search/functions_6.js +13 -11
- package/SVF-doxygen/html/html/search/functions_8.js +4 -4
- package/SVF-doxygen/html/html/search/functions_c.js +1 -1
- package/SVF-doxygen/html/html/search/functions_d.js +1 -1
- package/SVF-doxygen/html/html/search/functions_e.js +4 -4
- package/SVF-doxygen/html/html/search/related_0.js +2 -1
- package/SVF-doxygen/html/html/search/searchdata.js +3 -3
- package/SVF-doxygen/html/html/search/typedefs_1.js +2 -2
- package/SVF-doxygen/html/html/search/typedefs_16.html +26 -0
- package/SVF-doxygen/html/html/search/typedefs_16.js +4 -0
- package/SVF-doxygen/html/html/search/typedefs_2.js +1 -1
- package/SVF-doxygen/html/html/search/typedefs_8.js +2 -1
- package/SVF-doxygen/html/html/search/variables_1.js +0 -1
- package/SVF-doxygen/html/html/search/variables_13.js +1 -1
- package/SVF-doxygen/html/html/search/variables_14.js +1 -1
- package/SVF-doxygen/html/html/search/variables_15.js +1 -1
- package/SVF-doxygen/html/html/search/variables_2.js +2 -3
- package/SVF-doxygen/html/html/search/variables_3.js +2 -1
- package/SVF-doxygen/html/html/search/variables_5.js +1 -1
- package/SVF-doxygen/html/html/search/variables_9.js +2 -0
- package/SVF-doxygen/html/html/search/variables_d.js +2 -2
- package/SVF-doxygen/html/html/search/variables_e.js +3 -3
- package/include/SABER/PathCondAllocator.h +2 -3
- package/include/Util/Conditions.h +272 -166
- package/include/Util/Options.h +4 -0
- package/index.html +2 -0
- package/lib/SABER/PathCondAllocator.cpp +3 -0
- package/lib/Util/Conditions.cpp +245 -209
- package/lib/Util/Options.cpp +11 -0
- package/lib/WPA/Andersen.cpp +10 -9
- package/package.json +1 -1
|
@@ -36,280 +36,386 @@
|
|
|
36
36
|
#include "CUDD/cuddInt.h"
|
|
37
37
|
#include "z3++.h"
|
|
38
38
|
|
|
39
|
-
namespace SVF
|
|
40
|
-
{
|
|
39
|
+
namespace SVF {
|
|
41
40
|
|
|
42
|
-
class CondExpr{
|
|
41
|
+
class CondExpr {
|
|
43
42
|
public:
|
|
44
43
|
|
|
45
|
-
enum CondExprKind
|
|
46
|
-
|
|
47
|
-
BranchK
|
|
44
|
+
enum CondExprKind {
|
|
45
|
+
BDDK, Z3K
|
|
48
46
|
};
|
|
49
47
|
|
|
50
|
-
CondExpr(
|
|
48
|
+
CondExpr(CondExprKind _k) : condExprK(_k) {
|
|
51
49
|
}
|
|
52
|
-
virtual ~CondExpr(){
|
|
53
50
|
|
|
54
|
-
|
|
55
|
-
const z3::expr& getExpr() const{
|
|
56
|
-
return e;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/// get ctx
|
|
60
|
-
inline z3::context& getContext() const {
|
|
61
|
-
return getExpr().ctx();
|
|
62
|
-
}
|
|
51
|
+
virtual ~CondExpr() {
|
|
63
52
|
|
|
64
|
-
/// get id
|
|
65
|
-
inline u32_t getId() const {
|
|
66
|
-
return getExpr().id();
|
|
67
53
|
}
|
|
68
54
|
|
|
69
55
|
/// get Condition kind
|
|
70
|
-
inline CondExprKind getCondKind() const{
|
|
56
|
+
inline CondExprKind getCondKind() const {
|
|
71
57
|
return condExprK;
|
|
72
58
|
}
|
|
73
59
|
|
|
74
60
|
private:
|
|
75
|
-
z3::expr e;
|
|
76
61
|
CondExprKind condExprK;
|
|
77
62
|
};
|
|
78
63
|
|
|
79
|
-
class
|
|
80
|
-
|
|
64
|
+
class Z3Expr : public CondExpr {
|
|
81
65
|
public:
|
|
82
|
-
typedef
|
|
83
|
-
|
|
66
|
+
typedef z3::expr Z3Cond;
|
|
67
|
+
|
|
68
|
+
Z3Expr(const z3::expr &_e) : CondExpr(Z3K), e(_e) {
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
virtual ~Z3Expr() {
|
|
72
|
+
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const Z3Cond &getExpr() const {
|
|
76
|
+
return e;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/// get ctx
|
|
80
|
+
inline z3::context &getContext() const {
|
|
81
|
+
return getExpr().ctx();
|
|
84
82
|
}
|
|
85
83
|
|
|
86
|
-
/// get
|
|
87
|
-
|
|
88
|
-
return
|
|
84
|
+
/// get id
|
|
85
|
+
inline NodeID getId() const {
|
|
86
|
+
return getExpr().id();
|
|
89
87
|
}
|
|
90
88
|
|
|
91
89
|
/// Methods for support type inquiry through isa, cast, and dyn_cast:
|
|
92
90
|
//@{
|
|
93
|
-
static inline bool classof(const
|
|
94
|
-
{
|
|
91
|
+
static inline bool classof(const Z3Expr *) {
|
|
95
92
|
return true;
|
|
96
93
|
}
|
|
97
94
|
|
|
98
|
-
static inline bool classof(const CondExpr *cond)
|
|
99
|
-
|
|
100
|
-
return cond->getCondKind() == BranchK;
|
|
95
|
+
static inline bool classof(const CondExpr *cond) {
|
|
96
|
+
return cond->getCondKind() == Z3K;
|
|
101
97
|
}
|
|
102
98
|
//@}
|
|
103
99
|
|
|
104
|
-
|
|
105
100
|
private:
|
|
106
|
-
|
|
101
|
+
Z3Cond e;
|
|
107
102
|
|
|
108
103
|
};
|
|
109
104
|
|
|
105
|
+
class BDDExpr : public CondExpr {
|
|
110
106
|
|
|
111
|
-
/**
|
|
112
|
-
* Branch Condition Manager
|
|
113
|
-
*/
|
|
114
|
-
class BranchCondManager
|
|
115
|
-
{
|
|
116
107
|
public:
|
|
117
|
-
typedef
|
|
118
|
-
/// Constructor
|
|
119
|
-
BranchCondManager()
|
|
120
|
-
{
|
|
121
|
-
m_bdd_mgr = Cudd_Init(0, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0);
|
|
122
|
-
}
|
|
108
|
+
typedef DdNode BDDCond;
|
|
123
109
|
|
|
124
|
-
|
|
125
|
-
~BranchCondManager()
|
|
126
|
-
{
|
|
127
|
-
Cudd_Quit(m_bdd_mgr);
|
|
110
|
+
BDDExpr(BDDCond *_bddCond) : CondExpr(BDDK), bddCond(_bddCond) {
|
|
128
111
|
}
|
|
129
112
|
|
|
130
|
-
|
|
131
|
-
{
|
|
132
|
-
return
|
|
133
|
-
}
|
|
134
|
-
inline BranchCond* getTrueCond() const
|
|
135
|
-
{
|
|
136
|
-
return BddOne();
|
|
137
|
-
}
|
|
138
|
-
inline BranchCond* getFalseCond() const
|
|
139
|
-
{
|
|
140
|
-
return BddZero();
|
|
113
|
+
/// get BDD condition
|
|
114
|
+
BDDCond *getBDDCond() const {
|
|
115
|
+
return bddCond;
|
|
141
116
|
}
|
|
142
117
|
|
|
143
|
-
|
|
144
|
-
{
|
|
145
|
-
|
|
118
|
+
/// Methods for support type inquiry through isa, cast, and dyn_cast:
|
|
119
|
+
//@{
|
|
120
|
+
static inline bool classof(const BDDExpr *) {
|
|
121
|
+
return true;
|
|
146
122
|
}
|
|
147
|
-
|
|
148
|
-
{
|
|
149
|
-
return
|
|
123
|
+
|
|
124
|
+
static inline bool classof(const CondExpr *cond) {
|
|
125
|
+
return cond->getCondKind() == BDDK;
|
|
150
126
|
}
|
|
151
|
-
/// Operations on conditions.
|
|
152
|
-
//@{
|
|
153
|
-
BranchCond* AND(BranchCond* lhs, BranchCond* rhs);
|
|
154
|
-
BranchCond* OR(BranchCond* lhs, BranchCond* rhs);
|
|
155
|
-
BranchCond* NEG(BranchCond* lhs);
|
|
156
127
|
//@}
|
|
157
128
|
|
|
158
|
-
/**
|
|
159
|
-
* Utilities for dumping conditions. These methods use global functions from CUDD
|
|
160
|
-
* package and they can be removed outside this class scope to be used by others.
|
|
161
|
-
*/
|
|
162
|
-
void ddClearFlag(BranchCond * f) const;
|
|
163
|
-
void BddSupportStep( BranchCond * f, NodeBS &support) const;
|
|
164
|
-
void extractSubConds( BranchCond * f, NodeBS &support) const;
|
|
165
|
-
void dump(BranchCond* lhs, OutStream & O);
|
|
166
|
-
std::string dumpStr(BranchCond* lhs) const;
|
|
167
129
|
|
|
168
130
|
private:
|
|
169
|
-
|
|
170
|
-
{
|
|
171
|
-
return Cudd_ReadOne(m_bdd_mgr);
|
|
172
|
-
}
|
|
173
|
-
inline BranchCond* BddZero() const
|
|
174
|
-
{
|
|
175
|
-
return Cudd_ReadLogicZero(m_bdd_mgr);
|
|
176
|
-
}
|
|
131
|
+
BDDCond *bddCond;
|
|
177
132
|
|
|
178
|
-
DdManager *m_bdd_mgr;
|
|
179
133
|
};
|
|
180
134
|
|
|
181
|
-
class CondManager{
|
|
135
|
+
class CondManager {
|
|
136
|
+
|
|
137
|
+
public:
|
|
138
|
+
enum CondMgrKind {
|
|
139
|
+
BDDMgrK, Z3MgrK
|
|
140
|
+
};
|
|
182
141
|
|
|
183
142
|
private:
|
|
184
|
-
static CondManager*
|
|
143
|
+
static CondManager *condMgr;
|
|
185
144
|
|
|
145
|
+
protected:
|
|
186
146
|
/// Constructor
|
|
187
|
-
CondManager()
|
|
147
|
+
CondManager() {}
|
|
188
148
|
|
|
189
149
|
public:
|
|
190
|
-
typedef
|
|
191
|
-
typedef Map<const CondExpr*, const Instruction* > CondToTermInstMap; // map a condition to its branch instruction
|
|
150
|
+
typedef Map<const CondExpr *, const Instruction *> CondToTermInstMap; // map a condition to its branch instruction
|
|
192
151
|
static u32_t totalCondNum; // a counter for fresh condition
|
|
193
152
|
/// Singleton design here to make sure we only have one instance during any analysis
|
|
194
153
|
//@{
|
|
195
|
-
static
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
{
|
|
199
|
-
condMgr = new CondManager();
|
|
200
|
-
}
|
|
201
|
-
return condMgr;
|
|
202
|
-
}
|
|
203
|
-
static void releaseCondMgr()
|
|
204
|
-
{
|
|
154
|
+
static CondManager *getCondMgr(CondMgrKind _condMgrKind);
|
|
155
|
+
|
|
156
|
+
static void releaseCondMgr() {
|
|
205
157
|
delete condMgr;
|
|
206
158
|
condMgr = nullptr;
|
|
207
159
|
}
|
|
208
160
|
//@}
|
|
209
161
|
|
|
210
|
-
typedef Map<u32_t, CondExpr*> IDToCondExprMap;
|
|
211
|
-
typedef Map<BranchCond*, CondExpr*> BranchCondToCondExprMap;
|
|
212
|
-
|
|
213
162
|
/// Destructor
|
|
214
|
-
~CondManager();
|
|
163
|
+
virtual ~CondManager() {};
|
|
215
164
|
|
|
216
165
|
/// Create a fresh condition to encode each program branch
|
|
217
|
-
CondExpr*
|
|
218
|
-
|
|
219
|
-
/// Get or add a single branch condition, e.g., when doing condition conjunction
|
|
220
|
-
CondExpr* getOrAddBranchCond(const z3::expr& e, BranchCond* branchCond);
|
|
166
|
+
virtual CondExpr *createFreshBranchCond(const Instruction *inst) = 0;
|
|
221
167
|
|
|
222
168
|
/// Return the number of condition expressions
|
|
223
|
-
u32_t getCondNumber();
|
|
169
|
+
virtual u32_t getCondNumber() = 0;
|
|
224
170
|
|
|
225
171
|
/// Return the unique true condition
|
|
226
|
-
inline CondExpr*
|
|
227
|
-
{
|
|
172
|
+
inline CondExpr *getTrueCond() const {
|
|
228
173
|
return trueCond;
|
|
229
174
|
}
|
|
175
|
+
|
|
230
176
|
/// Return the unique false condition
|
|
231
|
-
inline CondExpr*
|
|
232
|
-
{
|
|
177
|
+
inline CondExpr *getFalseCond() const {
|
|
233
178
|
return falseCond;
|
|
234
179
|
}
|
|
235
180
|
|
|
236
|
-
/// Preprocess the condition, e.g., Compressing using And-Inverter-Graph
|
|
237
|
-
z3::expr simplify(const z3::expr& expr) const;
|
|
238
181
|
/// Operations on conditions.
|
|
239
182
|
//@{
|
|
240
|
-
CondExpr*
|
|
241
|
-
CondExpr* OR(CondExpr* lhs, CondExpr* rhs);
|
|
242
|
-
CondExpr* NEG(CondExpr* lhs);
|
|
243
|
-
//@}
|
|
183
|
+
virtual CondExpr *AND(CondExpr *lhs, CondExpr *rhs) = 0;
|
|
244
184
|
|
|
245
|
-
|
|
246
|
-
std::string getMemUsage();
|
|
185
|
+
virtual CondExpr *OR(CondExpr *lhs, CondExpr *rhs) = 0;
|
|
247
186
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
/// Print out one particular expression
|
|
252
|
-
void printDbg(const CondExpr* e);
|
|
187
|
+
virtual CondExpr *NEG(CondExpr *lhs) = 0;
|
|
188
|
+
//@}
|
|
253
189
|
|
|
254
|
-
|
|
255
|
-
std::string dumpStr(const CondExpr* e) const;
|
|
256
|
-
|
|
257
|
-
/// Extract sub conditions of this expression
|
|
258
|
-
void extractSubConds(const CondExpr* cond, NodeBS &support) const;
|
|
190
|
+
virtual bool isNegCond(const CondExpr *cond) const = 0;
|
|
259
191
|
|
|
260
192
|
/// Whether the condition is satisfiable
|
|
261
|
-
bool isSatisfiable(const CondExpr*
|
|
193
|
+
virtual bool isSatisfiable(const CondExpr *cond) = 0;
|
|
262
194
|
|
|
263
195
|
/// Whether lhs and rhs are equivalent branch conditions
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
SVFUtil::dyn_cast<BranchCondExpr>(rhs)->getBranchCond();
|
|
267
|
-
}
|
|
196
|
+
virtual bool isEquivalentBranchCond(const CondExpr *lhs, const CondExpr *rhs) = 0;
|
|
197
|
+
|
|
268
198
|
/// Whether **All Paths** are reachable
|
|
269
|
-
bool isAllPathReachable(const CondExpr*
|
|
199
|
+
bool isAllPathReachable(const CondExpr *e);
|
|
270
200
|
|
|
271
201
|
/// Get condition using condition id (z3 ast id)
|
|
272
|
-
|
|
273
|
-
const IDToCondExprMap::const_iterator it = allocatedConds.find(id);
|
|
274
|
-
assert(it!=allocatedConds.end() && "condition not found!");
|
|
275
|
-
return it->second;
|
|
276
|
-
}
|
|
202
|
+
virtual CondExpr *getCond(u32_t id) const = 0;
|
|
277
203
|
|
|
278
204
|
/// Get/Set llvm conditional expression
|
|
279
205
|
//{@
|
|
280
|
-
inline const Instruction*
|
|
281
|
-
{
|
|
206
|
+
inline const Instruction *getCondInst(const CondExpr *cond) const {
|
|
282
207
|
CondToTermInstMap::const_iterator it = condToInstMap.find(cond);
|
|
283
|
-
assert(it!=condToInstMap.end() && "this should be a fresh condition");
|
|
208
|
+
assert(it != condToInstMap.end() && "this should be a fresh condition");
|
|
284
209
|
return it->second;
|
|
285
210
|
}
|
|
286
|
-
|
|
287
|
-
|
|
211
|
+
|
|
212
|
+
inline void setCondInst(const CondExpr *cond, const Instruction *inst) {
|
|
213
|
+
assert(condToInstMap.find(cond) == condToInstMap.end() && "this should be a fresh condition");
|
|
288
214
|
condToInstMap[cond] = inst;
|
|
289
215
|
}
|
|
216
|
+
//@}
|
|
217
|
+
|
|
218
|
+
/// Return memory usage for this condition manager
|
|
219
|
+
virtual std::string getMemUsage() = 0;
|
|
220
|
+
|
|
221
|
+
/// Return string format of this expression
|
|
222
|
+
virtual std::string dumpStr(const CondExpr *e) const = 0;
|
|
223
|
+
|
|
224
|
+
/// Extract sub conditions of this expression
|
|
225
|
+
virtual void extractSubConds(const CondExpr *cond, NodeBS &support) const = 0;
|
|
226
|
+
|
|
227
|
+
protected:
|
|
228
|
+
static CondExpr *trueCond;
|
|
229
|
+
static CondExpr *falseCond;
|
|
230
|
+
|
|
231
|
+
private:
|
|
232
|
+
|
|
233
|
+
CondToTermInstMap condToInstMap; ///< map condition to llvm instruction
|
|
234
|
+
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Z3 Condition Manager
|
|
239
|
+
*/
|
|
240
|
+
class Z3Manager : public CondManager {
|
|
241
|
+
friend class CondManager;
|
|
242
|
+
|
|
243
|
+
public:
|
|
244
|
+
typedef Z3Expr::Z3Cond Z3Cond;
|
|
245
|
+
typedef Map<u32_t, Z3Expr *> IDToCondExprMap;
|
|
246
|
+
|
|
247
|
+
private:
|
|
248
|
+
/// Constructor
|
|
249
|
+
Z3Manager();
|
|
250
|
+
|
|
251
|
+
IDToCondExprMap idToCondExprMap;
|
|
252
|
+
z3::context cxt;
|
|
253
|
+
z3::solver sol;
|
|
254
|
+
NodeBS negConds;
|
|
255
|
+
|
|
256
|
+
public:
|
|
257
|
+
|
|
258
|
+
/// Destructor
|
|
259
|
+
virtual ~Z3Manager();
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
inline u32_t getCondNumber() override {
|
|
263
|
+
return sol.get_model().size();
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/// Preprocess the condition, e.g., Compressing using And-Inverter-Graph
|
|
267
|
+
z3::expr simplify(const z3::expr &expr) const;
|
|
268
|
+
|
|
269
|
+
/// Given an id, get its condition
|
|
270
|
+
CondExpr *getCond(u32_t i) const override {
|
|
271
|
+
auto it = idToCondExprMap.find(i);
|
|
272
|
+
assert(it != idToCondExprMap.end() && "condition not found!");
|
|
273
|
+
return it->second;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
CondExpr *createFreshBranchCond(const Instruction *inst) override;
|
|
277
|
+
|
|
278
|
+
Z3Expr *getOrAddZ3Cond(const Z3Cond &z3Cond);
|
|
279
|
+
|
|
280
|
+
/// Operations on conditions.
|
|
281
|
+
//@{
|
|
282
|
+
CondExpr *AND(CondExpr *lhs, CondExpr *rhs) override;
|
|
283
|
+
|
|
284
|
+
CondExpr *OR(CondExpr *lhs, CondExpr *rhs) override;
|
|
285
|
+
|
|
286
|
+
CondExpr *NEG(CondExpr *lhs) override;
|
|
287
|
+
//@}
|
|
288
|
+
|
|
289
|
+
bool isSatisfiable(const CondExpr *cond) override;
|
|
290
|
+
|
|
291
|
+
bool isEquivalentBranchCond(const CondExpr *lhs, const CondExpr *rhs) override;
|
|
290
292
|
|
|
291
293
|
inline void setNegCondInst(const CondExpr *cond, const Instruction *inst) {
|
|
292
294
|
setCondInst(cond, inst);
|
|
293
|
-
|
|
295
|
+
const Z3Expr *z3CondExpr = SVFUtil::dyn_cast<Z3Expr>(cond);
|
|
296
|
+
assert(z3CondExpr && "not z3 condition.");
|
|
297
|
+
negConds.set(z3CondExpr->getId());
|
|
294
298
|
}
|
|
295
299
|
|
|
296
|
-
|
|
297
|
-
|
|
300
|
+
bool isNegCond(const CondExpr *cond) const override {
|
|
301
|
+
const Z3Expr *z3CondExpr = SVFUtil::dyn_cast<Z3Expr>(cond);
|
|
302
|
+
assert(z3CondExpr && "not z3 condition.");
|
|
303
|
+
return negConds.test(z3CondExpr->getId());
|
|
298
304
|
}
|
|
299
|
-
|
|
305
|
+
|
|
306
|
+
void extractSubConds(const CondExpr *f, NodeBS &support) const override;
|
|
307
|
+
|
|
308
|
+
std::string dumpStr(const CondExpr *e) const override;
|
|
309
|
+
|
|
310
|
+
inline std::string getMemUsage() override {
|
|
311
|
+
return "";
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/// Print out one particular expression
|
|
315
|
+
void printDbg(const CondExpr *e);
|
|
316
|
+
|
|
317
|
+
/// Dump out all expressions
|
|
318
|
+
void printModel();
|
|
319
|
+
};
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* BDD Condition Manager
|
|
324
|
+
*/
|
|
325
|
+
class BDDManager : public CondManager {
|
|
326
|
+
friend class CondManager;
|
|
327
|
+
|
|
328
|
+
public:
|
|
329
|
+
typedef BDDExpr::BDDCond BDDCond;
|
|
330
|
+
typedef Map<BDDCond *, BDDExpr *> BDDToBDDCondExpr;
|
|
331
|
+
typedef Map<u32_t, BDDCond *> IndexToBDDCond;
|
|
300
332
|
|
|
301
333
|
private:
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
334
|
+
|
|
335
|
+
/// Constructor
|
|
336
|
+
BDDManager();
|
|
337
|
+
|
|
338
|
+
inline BDDCond *BddOne() const {
|
|
339
|
+
return Cudd_ReadOne(m_bdd_mgr);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
inline BDDCond *BddZero() const {
|
|
343
|
+
return Cudd_ReadLogicZero(m_bdd_mgr);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
DdManager *m_bdd_mgr;
|
|
347
|
+
BDDToBDDCondExpr bddToBddCondExprMap;
|
|
348
|
+
IndexToBDDCond indexToBddCondMap;
|
|
349
|
+
|
|
350
|
+
public:
|
|
351
|
+
|
|
352
|
+
/// Destructor
|
|
353
|
+
virtual ~BDDManager();
|
|
354
|
+
|
|
355
|
+
BDDCond *createCond(u32_t i) {
|
|
356
|
+
assert(indexToBddCondMap.find(i) == indexToBddCondMap.end() &&
|
|
357
|
+
"This should be fresh index to create new BDD");
|
|
358
|
+
BDDCond *bddCond = Cudd_bddIthVar(m_bdd_mgr, i);
|
|
359
|
+
return indexToBddCondMap.emplace(i, bddCond).first->second;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
/// Given an index, get its condition
|
|
363
|
+
CondExpr *getCond(u32_t i) const override {
|
|
364
|
+
auto it = indexToBddCondMap.find(i);
|
|
365
|
+
assert(it != indexToBddCondMap.end() && "condition not found!");
|
|
366
|
+
auto it2 = bddToBddCondExprMap.find(it->second);
|
|
367
|
+
assert(it2 != bddToBddCondExprMap.end() && "condition not found!");
|
|
368
|
+
return it2->second;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
CondExpr *createFreshBranchCond(const Instruction *inst) override;
|
|
372
|
+
|
|
373
|
+
inline u32_t getCondNumber() override {
|
|
374
|
+
return Cudd_ReadNodeCount(m_bdd_mgr);
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
BDDExpr *getOrAddBranchCond(BDDCond *bddCond);
|
|
378
|
+
|
|
379
|
+
/// Operations on conditions.
|
|
380
|
+
//@{
|
|
381
|
+
CondExpr *AND(CondExpr *lhs, CondExpr *rhs) override;
|
|
382
|
+
|
|
383
|
+
CondExpr *OR(CondExpr *lhs, CondExpr *rhs) override;
|
|
384
|
+
|
|
385
|
+
CondExpr *NEG(CondExpr *lhs) override;
|
|
386
|
+
//@}
|
|
387
|
+
|
|
388
|
+
bool isNegCond(const CondExpr *cond) const override {
|
|
389
|
+
return false;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
bool isEquivalentBranchCond(const CondExpr *lhs, const CondExpr *rhs) override {
|
|
393
|
+
return lhs == rhs;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
bool isSatisfiable(const CondExpr *cond) override;
|
|
397
|
+
|
|
398
|
+
/**
|
|
399
|
+
* Utilities for dumping conditions. These methods use global functions from CUDD
|
|
400
|
+
* package and they can be removed outside this class scope to be used by others.
|
|
401
|
+
*/
|
|
402
|
+
void ddClearFlag(BDDCond *f) const;
|
|
403
|
+
|
|
404
|
+
void BddSupportStep(BDDCond *f, NodeBS &support) const;
|
|
405
|
+
|
|
406
|
+
void extractSubConds(const CondExpr *f, NodeBS &support) const override;
|
|
407
|
+
|
|
408
|
+
void dump(const CondExpr *lhs, OutStream &O);
|
|
409
|
+
|
|
410
|
+
std::string dumpStr(const CondExpr *e) const override;
|
|
411
|
+
|
|
412
|
+
inline std::string getMemUsage() override {
|
|
413
|
+
return std::to_string(Cudd_ReadMemoryInUse(m_bdd_mgr));
|
|
414
|
+
}
|
|
415
|
+
|
|
311
416
|
};
|
|
312
417
|
|
|
418
|
+
|
|
313
419
|
} // End namespace SVF
|
|
314
420
|
|
|
315
421
|
#endif /* BITVECTORCOND_H_ */
|
package/include/Util/Options.h
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
#include "Util/NodeIDAllocator.h"
|
|
11
11
|
#include "MSSA/MemSSA.h"
|
|
12
12
|
#include "WPA/WPAPass.h"
|
|
13
|
+
#include "Util/Conditions.h"
|
|
13
14
|
|
|
14
15
|
namespace SVF
|
|
15
16
|
{
|
|
@@ -253,6 +254,9 @@ public:
|
|
|
253
254
|
|
|
254
255
|
// DOTGraphTraits
|
|
255
256
|
static const llvm::cl::opt<bool> ShowHiddenNode;
|
|
257
|
+
|
|
258
|
+
// Conditions
|
|
259
|
+
static const llvm::cl::opt<CondManager::CondMgrKind> ConditionType;
|
|
256
260
|
};
|
|
257
261
|
} // namespace SVF
|
|
258
262
|
|
package/index.html
CHANGED
|
@@ -25,6 +25,8 @@
|
|
|
25
25
|
|
|
26
26
|
<p><a href="https://github.com/svf-tools/SVF">SVF</a> is a static tool that enables scalable and precise interprocedural dependence analysis for C and C++ programs. SVF allows value-flow construction and pointer analysis to be performed iteratively, thereby providing increasingly improved precision for both. </p>
|
|
27
27
|
|
|
28
|
+
For a pointer analysis framework that works for Java, we refer to <a href="https://qilinpta.github.io/"> Qilin</a>.
|
|
29
|
+
|
|
28
30
|
<h2>
|
|
29
31
|
<a id="what-kind-of-analyses-does-svf-provide" class="anchor" href="#what-kind-of-analyses-does-svf-provide" aria-hidden="true"><span class="octicon octicon-link"></span></a>What kind of analyses does SVF provide?</h2>
|
|
30
32
|
|