From 162aea2b923f27bd29c0c84b60cfe36b70650b3e Mon Sep 17 00:00:00 2001 From: bjjwwang Date: Mon, 26 Feb 2024 13:50:38 +1100 Subject: [PATCH 01/22] tmp add Sparse ICFG --- svf/include/AE/Svfexe/AbstractExecution.h | 4 + svf/include/Graphs/ICFG.h | 20 +- svf/include/Util/Options.h | 2 + svf/lib/AE/Svfexe/AbstractExecution.cpp | 232 +++++++++++++++++++++- svf/lib/Graphs/ICFG.cpp | 8 + svf/lib/Util/Options.cpp | 3 +- 6 files changed, 257 insertions(+), 12 deletions(-) diff --git a/svf/include/AE/Svfexe/AbstractExecution.h b/svf/include/AE/Svfexe/AbstractExecution.h index 37db43ecf..20025738c 100644 --- a/svf/include/AE/Svfexe/AbstractExecution.h +++ b/svf/include/AE/Svfexe/AbstractExecution.h @@ -253,6 +253,8 @@ class AbstractExecution Set _recursiveFuns; private: + void compressICFGGraph(); + // helper functions in handleCallSite virtual bool isExtCall(const CallICFGNode* callNode); virtual void extCallPass(const CallICFGNode* callNode); @@ -274,6 +276,8 @@ class AbstractExecution // private data Map _preES; Map _postES; + Map> _subICFGNode; + Map _refICFGNode; std::string _moduleName; }; diff --git a/svf/include/Graphs/ICFG.h b/svf/include/Graphs/ICFG.h index b3514ca2b..f00cd47cc 100644 --- a/svf/include/Graphs/ICFG.h +++ b/svf/include/Graphs/ICFG.h @@ -147,6 +147,16 @@ class ICFG : public GenericICFGTy return icfgNodeToSVFLoopVec; } + /// Add ICFG edge + inline bool addICFGEdge(ICFGEdge* edge) + { + bool added1 = edge->getDstNode()->addIncomingEdge(edge); + bool added2 = edge->getSrcNode()->addOutgoingEdge(edge); + bool all_added = added1 && added2; + assert(all_added && "ICFGEdge not added?"); + return all_added; + } + protected: /// Remove a SVFG edge inline void removeICFGEdge(ICFGEdge* edge) @@ -180,16 +190,6 @@ class ICFG : public GenericICFGTy } } - /// Add ICFG edge - inline bool addICFGEdge(ICFGEdge* edge) - { - bool added1 = edge->getDstNode()->addIncomingEdge(edge); - bool added2 = edge->getSrcNode()->addOutgoingEdge(edge); - bool all_added = added1 && added2; - assert(all_added && "ICFGEdge not added?"); - return all_added; - } - /// Add a ICFG node virtual inline void addICFGNode(ICFGNode* node) { diff --git a/svf/include/Util/Options.h b/svf/include/Util/Options.h index fe1be2d7c..e87bd6083 100644 --- a/svf/include/Util/Options.h +++ b/svf/include/Util/Options.h @@ -272,6 +272,8 @@ class Options /// if the access index of gepstmt is unknown, skip it, Default: false static const Option GepUnknownIdx; static const Option RunUncallFuncs; + + static const Option Sparse; }; } // namespace SVF diff --git a/svf/lib/AE/Svfexe/AbstractExecution.cpp b/svf/lib/AE/Svfexe/AbstractExecution.cpp index 41aaf4df2..99e73c63a 100644 --- a/svf/lib/AE/Svfexe/AbstractExecution.cpp +++ b/svf/lib/AE/Svfexe/AbstractExecution.cpp @@ -142,6 +142,224 @@ AbstractExecution::~AbstractExecution() } +void AbstractExecution::compressICFGGraph() +{ + Map> bbToNodes; + for (const auto &func : *PAG::getPAG()->getModule()) + { + for(const auto& bb: *func) + { + for(const auto& inst: *bb) + { + if(SVFUtil::isIntrinsicInst(inst)) continue; + const ICFGNode* icfgNode = _icfg->getICFGNode(inst); + // e.g. + // block: entry + // insts: call = i32 %fun(i32 %arg) + // We put the callnode in an icfgnode alone, and the retnode is similar. + if (const CallICFGNode *callNode = SVFUtil::dyn_cast(icfgNode)) + { + _refICFGNode[callNode] = callNode; + _subICFGNode[callNode] = {callNode}; + bbToNodes[bb].push_back(callNode); + + const RetICFGNode* retNode = callNode->getRetICFGNode(); + _refICFGNode[retNode] = retNode; + _subICFGNode[retNode] = {retNode}; + bbToNodes[bb].push_back(retNode); + } + else + { + // For ordinary instructions, we put multiple instructions in an ICFGNode + if (bbToNodes.find(bb) == bbToNodes.end()) + { + _subICFGNode[icfgNode] = {icfgNode}; + _refICFGNode[icfgNode] = icfgNode; + bbToNodes[bb] = {icfgNode}; + } + else + { + const ICFGNode* pNode = bbToNodes[bb].back(); + _subICFGNode[pNode].push_back(icfgNode); + _refICFGNode[icfgNode] = pNode; + } + } + } + } + + if (const FunEntryICFGNode* funEntryNode = _icfg->getFunEntryICFGNode(func)) + { + if(const SVFBasicBlock* bb = funEntryNode->getBB()) + { + std::vector& nodes = bbToNodes[bb]; + _subICFGNode[funEntryNode] = {funEntryNode}; + _refICFGNode[funEntryNode] = funEntryNode; + nodes.insert(nodes.begin(), funEntryNode); + } + } + if (const FunExitICFGNode* funExitNode = _icfg->getFunExitICFGNode(func)) + { + if(const SVFBasicBlock* bb = funExitNode->getBB()) + { + std::vector& nodes = bbToNodes[bb]; + _subICFGNode[funExitNode] = {funExitNode}; + _refICFGNode[funExitNode] = funExitNode; + nodes.push_back(funExitNode); + } + } + } + + Set rm_nodes; + for (auto it = _subICFGNode.begin(); it!= _subICFGNode.end(); ++it) { + for (auto it2 = it->second.begin(); it2!= it->second.end(); ++it2) { + const ICFGNode* node2 = *it2; + if (_subICFGNode.find(node2) == _subICFGNode.end()) { + rm_nodes.insert(const_cast(node2)); + } + } + } + /// reconnect the ICFGNodes, + /// 1. intraCFGEdges between different basicblocks, but in the safe function + /// e.g. entry: + /// cond = icmp eq i32 %a, 0 ---------> srcblk + /// br i1 cond, label %bb1, label %bb2 ---------> srcblk_tail + /// bb1: + /// ... --------> dstblk + /// bb2: + /// ... --------> another dstblk + /// tmpEdge is the edge between srcblk and dstblk, may have condition var (cond is true or false) + for (const auto &node : *_icfg) + { + for (const auto &succ : node.second->getOutEdges()) + { + if (succ->isIntraCFGEdge()) + { + const SVFFunction *node_fun = node.second->getFun(); + const SVFFunction *succ_fun = succ->getDstNode()->getFun(); + const SVFBasicBlock *node_bb = node.second->getBB(); + const SVFBasicBlock *succ_bb = succ->getDstNode()->getBB(); + if (node_fun == succ_fun) + { + if (node_bb != succ_bb) + { + ICFGNode* srcblk = const_cast(bbToNodes[node_bb].back()); + ICFGNode* dstblk = const_cast(bbToNodes[succ_bb].front()); + ICFGNode* srcblk_tail = const_cast(_subICFGNode[bbToNodes[node_bb].back()].back()); + ICFGEdge* tmpEdge = _icfg->getICFGEdge(srcblk_tail, dstblk, ICFGEdge::ICFGEdgeK::IntraCF); + IntraCFGEdge *pEdge = nullptr; + if (tmpEdge) { + IntraCFGEdge* intraEdge = SVFUtil::dyn_cast(tmpEdge); + pEdge = new IntraCFGEdge(srcblk, dstblk); + if (intraEdge->getCondition()) + pEdge->setBranchCondition(intraEdge->getCondition(), intraEdge->getSuccessorCondValue()); + } + else { + pEdge = new IntraCFGEdge(srcblk, dstblk); + } + // avoid duplicate edges + if (srcblk->hasIncomingEdge(pEdge) || dstblk->hasIncomingEdge(pEdge)) + continue; + else + _icfg->addICFGEdge(pEdge); + } + } + } + } + } + + /// 2. intraCFGEdges in the same basicblock, but seperated by callInst + /// e.g. entry: + /// ..... --------> bbNode0 + /// call void @foo() ---------> callNode: bbNode1, retNode bbNode2 + /// ..... --------> bbNode3 + /// entry block has 4 bbNodes. the following for loop just links bbNodes in the same basic block. + for (const auto &bbNodes : bbToNodes) + { + for (u32_t i = 0; i < bbNodes.second.size() - 1; ++i) + { + ICFGNode* srcblk_tail = const_cast(_subICFGNode[bbNodes.second[i]].back()); + ICFGNode* srcblk = const_cast(bbNodes.second[i]); + ICFGNode* dstblk = const_cast( bbNodes.second[i+1]); + if (!_icfg->hasIntraICFGEdge(srcblk_tail, dstblk, ICFGEdge::ICFGEdgeK::IntraCF)) + continue; + IntraCFGEdge *pEdge = new IntraCFGEdge(srcblk, dstblk); + if (srcblk->hasIncomingEdge(pEdge) || dstblk->hasIncomingEdge(pEdge)) + continue; + else + _icfg->addICFGEdge(pEdge); + + } + } + + /// 3. CallCFGEdges and RetCFGEdges + /// CallEdge is the edge between CallNode and FunEntryNode. + /// RetEdge is the edge between FunExitNode and RetNode. + + for (const auto &bbNodes : bbToNodes) + { + for (u32_t i = 0; i < bbNodes.second.size(); ++i) + { + if (const CallICFGNode *callICFGNode = SVFUtil::dyn_cast( + bbNodes.second[i])) + { + for (const auto &icfgEdge : callICFGNode->getOutEdges()) + { + if (const CallCFGEdge *callEdge = SVFUtil::dyn_cast(icfgEdge)) + { + ICFGNode* srcblk = const_cast(bbNodes.second[i]); + ICFGNode* dstblk = const_cast(callEdge->getDstNode()); + ICFGEdge *pEdge = new ICFGEdge(srcblk, dstblk, ICFGEdge::ICFGEdgeK::CallCF); + if (srcblk->hasIncomingEdge(pEdge) || dstblk->hasIncomingEdge(pEdge)) + continue; + else + _icfg->addICFGEdge(pEdge); + } + } + } + else if (const RetICFGNode *retICFGNode = SVFUtil::dyn_cast( + bbNodes.second[i])) + { + for (const auto &icfgEdge : retICFGNode->getInEdges()) + { + if (const RetCFGEdge *retEdge = SVFUtil::dyn_cast(icfgEdge)) + { + if(!retEdge->getSrcNode()->getFun()->hasReturn()) continue; + ICFGNode* srcblk = const_cast(retEdge->getSrcNode()); + ICFGNode* dstblk = const_cast(bbNodes.second[i]); + ICFGEdge *pEdge = new ICFGEdge(srcblk, dstblk, ICFGEdge::ICFGEdgeK::RetCF); + if (srcblk->hasIncomingEdge(pEdge) || dstblk->hasIncomingEdge(pEdge)) + continue; + else + _icfg->addICFGEdge(pEdge); + } + } + } + else + { + + } + } + } + for (auto &it : rm_nodes) { + ICFGNode* node = it; + Set rm_outedges, rm_inedges; + for (ICFGEdge* edge : node->getOutEdges()) { + rm_outedges.insert(edge); + } + for (ICFGEdge* edge : node->getInEdges()) { + rm_inedges.insert(edge); + } + for (ICFGEdge* edge : rm_outedges) { + node->removeOutgoingEdge(edge); + edge->getDstNode()->removeIncomingEdge(edge); + } + for (ICFGEdge* edge : rm_inedges) { + node->removeIncomingEdge(edge); + edge->getSrcNode()->removeOutgoingEdge(edge); + } + } +} + void AbstractExecution::markRecursiveFuns() { // detect if callgraph has cycle @@ -159,6 +377,8 @@ void AbstractExecution::markRecursiveFuns() void AbstractExecution::analyse() { // handle Global ICFGNode of SVFModule + if (Options::Sparse()) + compressICFGGraph(); handleGlobalNode(); if (const SVFFunction* fun = _svfir->getModule()->getSVFFunction("main")) { @@ -600,7 +820,17 @@ void AbstractExecution::handleWTONode(const ICFGNode *node) } std::deque worklist; - handleICFGNode(node); + + if (Options::Sparse()) { + for (auto it = _subICFGNode[node].begin(); it != _subICFGNode[node].end(); ++it) { + const ICFGNode* curNode = *it; + handleICFGNode(curNode); + } + } + else { + handleICFGNode(node); + } + _preES.erase(node); _postES[node] = _svfir2ExeState->getEs(); } diff --git a/svf/lib/Graphs/ICFG.cpp b/svf/lib/Graphs/ICFG.cpp index bae8bff3e..28d1a2ef3 100644 --- a/svf/lib/Graphs/ICFG.cpp +++ b/svf/lib/Graphs/ICFG.cpp @@ -547,6 +547,14 @@ struct DOTGraphTraits : public DOTGraphTraits return node->toString(); } + static bool isNodeHidden(ICFGNode *node, ICFG *) + { + if (Options::ShowHiddenNode()) + return false; + else + return node->getInEdges().empty() && node->getOutEdges().empty(); + } + static std::string getNodeAttributes(NodeType *node, ICFG*) { std::string str; diff --git a/svf/lib/Util/Options.cpp b/svf/lib/Util/Options.cpp index 8ebe402a8..76dd123bb 100644 --- a/svf/lib/Util/Options.cpp +++ b/svf/lib/Util/Options.cpp @@ -851,5 +851,6 @@ const Option Options::GepUnknownIdx( "gep-unknown-idx","Skip Gep Unknown Index",false); const Option Options::RunUncallFuncs( "run-uncall-fun","Skip Gep Unknown Index",false); - +const Option Options::Sparse( + "sparse","Sparse",false); } // namespace SVF. From e202147724f03bc239f8a2d2223bf425b0c7736e Mon Sep 17 00:00:00 2001 From: bjjwwang Date: Mon, 26 Feb 2024 14:50:34 +1100 Subject: [PATCH 02/22] add ICFGSimplify --- svf/include/AE/Svfexe/AbstractExecution.h | 5 +- svf/include/AE/Svfexe/ICFGSimplify.h | 267 ++++++++++++++++++++++ svf/lib/AE/Svfexe/AbstractExecution.cpp | 226 +----------------- 3 files changed, 274 insertions(+), 224 deletions(-) create mode 100644 svf/include/AE/Svfexe/ICFGSimplify.h diff --git a/svf/include/AE/Svfexe/AbstractExecution.h b/svf/include/AE/Svfexe/AbstractExecution.h index 20025738c..ad6de2e9b 100644 --- a/svf/include/AE/Svfexe/AbstractExecution.h +++ b/svf/include/AE/Svfexe/AbstractExecution.h @@ -253,8 +253,6 @@ class AbstractExecution Set _recursiveFuns; private: - void compressICFGGraph(); - // helper functions in handleCallSite virtual bool isExtCall(const CallICFGNode* callNode); virtual void extCallPass(const CallICFGNode* callNode); @@ -276,8 +274,7 @@ class AbstractExecution // private data Map _preES; Map _postES; - Map> _subICFGNode; - Map _refICFGNode; + std::string _moduleName; }; diff --git a/svf/include/AE/Svfexe/ICFGSimplify.h b/svf/include/AE/Svfexe/ICFGSimplify.h new file mode 100644 index 000000000..61522381c --- /dev/null +++ b/svf/include/AE/Svfexe/ICFGSimplify.h @@ -0,0 +1,267 @@ +//===- ICFGSimplify.h -- Simplify ICFG----------------------------------// +// +// SVF: Static Value-Flow Analysis +// +// Copyright (C) <2013-> +// + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. + +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +// +// The implementation is based on +// Xiao Cheng, Jiawei Wang and Yulei Sui. Precise Sparse Abstract Execution via Cross-Domain Interaction. +// 46th International Conference on Software Engineering. (ICSE24) +//===----------------------------------------------------------------------===// + + +// +// Created by Jiawei Wang on 2024/2/25. +// +#include "Graphs/ICFG.h" + +namespace SVF{ +class ICFGSimplify { +public: +ICFGSimplify() = default; + +/// Simplify the ICFG by hiding the nodes in the same basic block +static void simplify(ICFG* _icfg) +{ + Map> bbToNodes; + for (const auto &func : *PAG::getPAG()->getModule()) + { + for(const auto& bb: *func) + { + for(const auto& inst: *bb) + { + if(SVFUtil::isIntrinsicInst(inst)) continue; + const ICFGNode* icfgNode = _icfg->getICFGNode(inst); + // e.g. + // block: entry + // insts: call = i32 %fun(i32 %arg) + // We put the callnode in an icfgnode alone, and the retnode is similar. + if (const CallICFGNode *callNode = SVFUtil::dyn_cast(icfgNode)) + { + _refICFGNode[callNode] = callNode; + _subICFGNode[callNode] = {callNode}; + bbToNodes[bb].push_back(callNode); + + const RetICFGNode* retNode = callNode->getRetICFGNode(); + _refICFGNode[retNode] = retNode; + _subICFGNode[retNode] = {retNode}; + bbToNodes[bb].push_back(retNode); + } + else + { + // For ordinary instructions, we put multiple instructions in an ICFGNode + if (bbToNodes.find(bb) == bbToNodes.end()) + { + _subICFGNode[icfgNode] = {icfgNode}; + _refICFGNode[icfgNode] = icfgNode; + bbToNodes[bb] = {icfgNode}; + } + else + { + const ICFGNode* pNode = bbToNodes[bb].back(); + _subICFGNode[pNode].push_back(icfgNode); + _refICFGNode[icfgNode] = pNode; + } + } + } + } + + if (const FunEntryICFGNode* funEntryNode = _icfg->getFunEntryICFGNode(func)) + { + if(const SVFBasicBlock* bb = funEntryNode->getBB()) + { + std::vector& nodes = bbToNodes[bb]; + _subICFGNode[funEntryNode] = {funEntryNode}; + _refICFGNode[funEntryNode] = funEntryNode; + nodes.insert(nodes.begin(), funEntryNode); + } + } + if (const FunExitICFGNode* funExitNode = _icfg->getFunExitICFGNode(func)) + { + if(const SVFBasicBlock* bb = funExitNode->getBB()) + { + std::vector& nodes = bbToNodes[bb]; + _subICFGNode[funExitNode] = {funExitNode}; + _refICFGNode[funExitNode] = funExitNode; + nodes.push_back(funExitNode); + } + } + } + + Set rm_nodes; + for (auto it = _subICFGNode.begin(); it!= _subICFGNode.end(); ++it) { + for (auto it2 = it->second.begin(); it2!= it->second.end(); ++it2) { + const ICFGNode* node2 = *it2; + if (_subICFGNode.find(node2) == _subICFGNode.end()) { + rm_nodes.insert(const_cast(node2)); + } + } + } + /// reconnect the ICFGNodes, + /// 1. intraCFGEdges between different basicblocks, but in the safe function + /// e.g. entry: + /// cond = icmp eq i32 %a, 0 ---------> srcblk + /// br i1 cond, label %bb1, label %bb2 ---------> srcblk_tail + /// bb1: + /// ... --------> dstblk + /// bb2: + /// ... --------> another dstblk + /// tmpEdge is the edge between srcblk and dstblk, may have condition var (cond is true or false) + for (const auto &node : *_icfg) + { + for (const auto &succ : node.second->getOutEdges()) + { + if (succ->isIntraCFGEdge()) + { + const SVFFunction *node_fun = node.second->getFun(); + const SVFFunction *succ_fun = succ->getDstNode()->getFun(); + const SVFBasicBlock *node_bb = node.second->getBB(); + const SVFBasicBlock *succ_bb = succ->getDstNode()->getBB(); + if (node_fun == succ_fun) + { + if (node_bb != succ_bb) + { + ICFGNode* srcblk = const_cast(bbToNodes[node_bb].back()); + ICFGNode* dstblk = const_cast(bbToNodes[succ_bb].front()); + ICFGNode* srcblk_tail = const_cast(_subICFGNode[bbToNodes[node_bb].back()].back()); + ICFGEdge* tmpEdge = _icfg->getICFGEdge(srcblk_tail, dstblk, ICFGEdge::ICFGEdgeK::IntraCF); + IntraCFGEdge *pEdge = nullptr; + if (tmpEdge) { + IntraCFGEdge* intraEdge = SVFUtil::dyn_cast(tmpEdge); + pEdge = new IntraCFGEdge(srcblk, dstblk); + if (intraEdge->getCondition()) + pEdge->setBranchCondition(intraEdge->getCondition(), intraEdge->getSuccessorCondValue()); + } + else { + pEdge = new IntraCFGEdge(srcblk, dstblk); + } + // avoid duplicate edges + if (srcblk->hasIncomingEdge(pEdge) || dstblk->hasIncomingEdge(pEdge)) + continue; + else + _icfg->addICFGEdge(pEdge); + } + } + } + } + } + + /// 2. intraCFGEdges in the same basicblock, but seperated by callInst + /// e.g. entry: + /// ..... --------> bbNode0 + /// call void @foo() ---------> callNode: bbNode1, retNode bbNode2 + /// ..... --------> bbNode3 + /// entry block has 4 bbNodes. the following for loop just links bbNodes in the same basic block. + for (const auto &bbNodes : bbToNodes) + { + for (u32_t i = 0; i < bbNodes.second.size() - 1; ++i) + { + ICFGNode* srcblk_tail = const_cast(_subICFGNode[bbNodes.second[i]].back()); + ICFGNode* srcblk = const_cast(bbNodes.second[i]); + ICFGNode* dstblk = const_cast( bbNodes.second[i+1]); + if (!_icfg->hasIntraICFGEdge(srcblk_tail, dstblk, ICFGEdge::ICFGEdgeK::IntraCF)) + continue; + IntraCFGEdge *pEdge = new IntraCFGEdge(srcblk, dstblk); + if (srcblk->hasIncomingEdge(pEdge) || dstblk->hasIncomingEdge(pEdge)) + continue; + else + _icfg->addICFGEdge(pEdge); + + } + } + + /// 3. CallCFGEdges and RetCFGEdges + /// CallEdge is the edge between CallNode and FunEntryNode. + /// RetEdge is the edge between FunExitNode and RetNode. + + for (const auto &bbNodes : bbToNodes) + { + for (u32_t i = 0; i < bbNodes.second.size(); ++i) + { + if (const CallICFGNode *callICFGNode = SVFUtil::dyn_cast( + bbNodes.second[i])) + { + for (const auto &icfgEdge : callICFGNode->getOutEdges()) + { + if (const CallCFGEdge *callEdge = SVFUtil::dyn_cast(icfgEdge)) + { + ICFGNode* srcblk = const_cast(bbNodes.second[i]); + ICFGNode* dstblk = const_cast(callEdge->getDstNode()); + ICFGEdge *pEdge = new ICFGEdge(srcblk, dstblk, ICFGEdge::ICFGEdgeK::CallCF); + if (srcblk->hasIncomingEdge(pEdge) || dstblk->hasIncomingEdge(pEdge)) + continue; + else + _icfg->addICFGEdge(pEdge); + } + } + } + else if (const RetICFGNode *retICFGNode = SVFUtil::dyn_cast( + bbNodes.second[i])) + { + for (const auto &icfgEdge : retICFGNode->getInEdges()) + { + if (const RetCFGEdge *retEdge = SVFUtil::dyn_cast(icfgEdge)) + { + if(!retEdge->getSrcNode()->getFun()->hasReturn()) continue; + ICFGNode* srcblk = const_cast(retEdge->getSrcNode()); + ICFGNode* dstblk = const_cast(bbNodes.second[i]); + ICFGEdge *pEdge = new ICFGEdge(srcblk, dstblk, ICFGEdge::ICFGEdgeK::RetCF); + if (srcblk->hasIncomingEdge(pEdge) || dstblk->hasIncomingEdge(pEdge)) + continue; + else + _icfg->addICFGEdge(pEdge); + } + } + } + else + { + + } + } + } + for (auto &it : rm_nodes) { + ICFGNode* node = it; + Set rm_outedges, rm_inedges; + for (ICFGEdge* edge : node->getOutEdges()) { + rm_outedges.insert(edge); + } + for (ICFGEdge* edge : node->getInEdges()) { + rm_inedges.insert(edge); + } + for (ICFGEdge* edge : rm_outedges) { + node->removeOutgoingEdge(edge); + edge->getDstNode()->removeIncomingEdge(edge); + } + for (ICFGEdge* edge : rm_inedges) { + node->removeIncomingEdge(edge); + edge->getSrcNode()->removeOutgoingEdge(edge); + } + } +} + +static const std::vector& getSubICFGNode(const ICFGNode* node) +{ + return _subICFGNode[node]; +} + + +private: + static Map> _subICFGNode; + static Map _refICFGNode; +}; +} + diff --git a/svf/lib/AE/Svfexe/AbstractExecution.cpp b/svf/lib/AE/Svfexe/AbstractExecution.cpp index 99e73c63a..7eb24c9c9 100644 --- a/svf/lib/AE/Svfexe/AbstractExecution.cpp +++ b/svf/lib/AE/Svfexe/AbstractExecution.cpp @@ -27,6 +27,7 @@ #include "WPA/Andersen.h" #include "SVFIR/SVFIR.h" #include "AE/Svfexe/AbstractExecution.h" +#include "AE/Svfexe/ICFGSimplify.h" #include "Util/Options.h" #include @@ -34,7 +35,8 @@ using namespace SVF; using namespace SVFUtil; using namespace z3; - +Map> ICFGSimplify::_subICFGNode; +Map ICFGSimplify::_refICFGNode; // according to varieties of cmp insts, // maybe var X var, var X const, const X var, const X const // we accept 'var X const' 'var X var' 'const X const' @@ -142,223 +144,7 @@ AbstractExecution::~AbstractExecution() } -void AbstractExecution::compressICFGGraph() -{ - Map> bbToNodes; - for (const auto &func : *PAG::getPAG()->getModule()) - { - for(const auto& bb: *func) - { - for(const auto& inst: *bb) - { - if(SVFUtil::isIntrinsicInst(inst)) continue; - const ICFGNode* icfgNode = _icfg->getICFGNode(inst); - // e.g. - // block: entry - // insts: call = i32 %fun(i32 %arg) - // We put the callnode in an icfgnode alone, and the retnode is similar. - if (const CallICFGNode *callNode = SVFUtil::dyn_cast(icfgNode)) - { - _refICFGNode[callNode] = callNode; - _subICFGNode[callNode] = {callNode}; - bbToNodes[bb].push_back(callNode); - - const RetICFGNode* retNode = callNode->getRetICFGNode(); - _refICFGNode[retNode] = retNode; - _subICFGNode[retNode] = {retNode}; - bbToNodes[bb].push_back(retNode); - } - else - { - // For ordinary instructions, we put multiple instructions in an ICFGNode - if (bbToNodes.find(bb) == bbToNodes.end()) - { - _subICFGNode[icfgNode] = {icfgNode}; - _refICFGNode[icfgNode] = icfgNode; - bbToNodes[bb] = {icfgNode}; - } - else - { - const ICFGNode* pNode = bbToNodes[bb].back(); - _subICFGNode[pNode].push_back(icfgNode); - _refICFGNode[icfgNode] = pNode; - } - } - } - } - - if (const FunEntryICFGNode* funEntryNode = _icfg->getFunEntryICFGNode(func)) - { - if(const SVFBasicBlock* bb = funEntryNode->getBB()) - { - std::vector& nodes = bbToNodes[bb]; - _subICFGNode[funEntryNode] = {funEntryNode}; - _refICFGNode[funEntryNode] = funEntryNode; - nodes.insert(nodes.begin(), funEntryNode); - } - } - if (const FunExitICFGNode* funExitNode = _icfg->getFunExitICFGNode(func)) - { - if(const SVFBasicBlock* bb = funExitNode->getBB()) - { - std::vector& nodes = bbToNodes[bb]; - _subICFGNode[funExitNode] = {funExitNode}; - _refICFGNode[funExitNode] = funExitNode; - nodes.push_back(funExitNode); - } - } - } - - Set rm_nodes; - for (auto it = _subICFGNode.begin(); it!= _subICFGNode.end(); ++it) { - for (auto it2 = it->second.begin(); it2!= it->second.end(); ++it2) { - const ICFGNode* node2 = *it2; - if (_subICFGNode.find(node2) == _subICFGNode.end()) { - rm_nodes.insert(const_cast(node2)); - } - } - } - /// reconnect the ICFGNodes, - /// 1. intraCFGEdges between different basicblocks, but in the safe function - /// e.g. entry: - /// cond = icmp eq i32 %a, 0 ---------> srcblk - /// br i1 cond, label %bb1, label %bb2 ---------> srcblk_tail - /// bb1: - /// ... --------> dstblk - /// bb2: - /// ... --------> another dstblk - /// tmpEdge is the edge between srcblk and dstblk, may have condition var (cond is true or false) - for (const auto &node : *_icfg) - { - for (const auto &succ : node.second->getOutEdges()) - { - if (succ->isIntraCFGEdge()) - { - const SVFFunction *node_fun = node.second->getFun(); - const SVFFunction *succ_fun = succ->getDstNode()->getFun(); - const SVFBasicBlock *node_bb = node.second->getBB(); - const SVFBasicBlock *succ_bb = succ->getDstNode()->getBB(); - if (node_fun == succ_fun) - { - if (node_bb != succ_bb) - { - ICFGNode* srcblk = const_cast(bbToNodes[node_bb].back()); - ICFGNode* dstblk = const_cast(bbToNodes[succ_bb].front()); - ICFGNode* srcblk_tail = const_cast(_subICFGNode[bbToNodes[node_bb].back()].back()); - ICFGEdge* tmpEdge = _icfg->getICFGEdge(srcblk_tail, dstblk, ICFGEdge::ICFGEdgeK::IntraCF); - IntraCFGEdge *pEdge = nullptr; - if (tmpEdge) { - IntraCFGEdge* intraEdge = SVFUtil::dyn_cast(tmpEdge); - pEdge = new IntraCFGEdge(srcblk, dstblk); - if (intraEdge->getCondition()) - pEdge->setBranchCondition(intraEdge->getCondition(), intraEdge->getSuccessorCondValue()); - } - else { - pEdge = new IntraCFGEdge(srcblk, dstblk); - } - // avoid duplicate edges - if (srcblk->hasIncomingEdge(pEdge) || dstblk->hasIncomingEdge(pEdge)) - continue; - else - _icfg->addICFGEdge(pEdge); - } - } - } - } - } - - /// 2. intraCFGEdges in the same basicblock, but seperated by callInst - /// e.g. entry: - /// ..... --------> bbNode0 - /// call void @foo() ---------> callNode: bbNode1, retNode bbNode2 - /// ..... --------> bbNode3 - /// entry block has 4 bbNodes. the following for loop just links bbNodes in the same basic block. - for (const auto &bbNodes : bbToNodes) - { - for (u32_t i = 0; i < bbNodes.second.size() - 1; ++i) - { - ICFGNode* srcblk_tail = const_cast(_subICFGNode[bbNodes.second[i]].back()); - ICFGNode* srcblk = const_cast(bbNodes.second[i]); - ICFGNode* dstblk = const_cast( bbNodes.second[i+1]); - if (!_icfg->hasIntraICFGEdge(srcblk_tail, dstblk, ICFGEdge::ICFGEdgeK::IntraCF)) - continue; - IntraCFGEdge *pEdge = new IntraCFGEdge(srcblk, dstblk); - if (srcblk->hasIncomingEdge(pEdge) || dstblk->hasIncomingEdge(pEdge)) - continue; - else - _icfg->addICFGEdge(pEdge); - - } - } - - /// 3. CallCFGEdges and RetCFGEdges - /// CallEdge is the edge between CallNode and FunEntryNode. - /// RetEdge is the edge between FunExitNode and RetNode. - - for (const auto &bbNodes : bbToNodes) - { - for (u32_t i = 0; i < bbNodes.second.size(); ++i) - { - if (const CallICFGNode *callICFGNode = SVFUtil::dyn_cast( - bbNodes.second[i])) - { - for (const auto &icfgEdge : callICFGNode->getOutEdges()) - { - if (const CallCFGEdge *callEdge = SVFUtil::dyn_cast(icfgEdge)) - { - ICFGNode* srcblk = const_cast(bbNodes.second[i]); - ICFGNode* dstblk = const_cast(callEdge->getDstNode()); - ICFGEdge *pEdge = new ICFGEdge(srcblk, dstblk, ICFGEdge::ICFGEdgeK::CallCF); - if (srcblk->hasIncomingEdge(pEdge) || dstblk->hasIncomingEdge(pEdge)) - continue; - else - _icfg->addICFGEdge(pEdge); - } - } - } - else if (const RetICFGNode *retICFGNode = SVFUtil::dyn_cast( - bbNodes.second[i])) - { - for (const auto &icfgEdge : retICFGNode->getInEdges()) - { - if (const RetCFGEdge *retEdge = SVFUtil::dyn_cast(icfgEdge)) - { - if(!retEdge->getSrcNode()->getFun()->hasReturn()) continue; - ICFGNode* srcblk = const_cast(retEdge->getSrcNode()); - ICFGNode* dstblk = const_cast(bbNodes.second[i]); - ICFGEdge *pEdge = new ICFGEdge(srcblk, dstblk, ICFGEdge::ICFGEdgeK::RetCF); - if (srcblk->hasIncomingEdge(pEdge) || dstblk->hasIncomingEdge(pEdge)) - continue; - else - _icfg->addICFGEdge(pEdge); - } - } - } - else - { - - } - } - } - for (auto &it : rm_nodes) { - ICFGNode* node = it; - Set rm_outedges, rm_inedges; - for (ICFGEdge* edge : node->getOutEdges()) { - rm_outedges.insert(edge); - } - for (ICFGEdge* edge : node->getInEdges()) { - rm_inedges.insert(edge); - } - for (ICFGEdge* edge : rm_outedges) { - node->removeOutgoingEdge(edge); - edge->getDstNode()->removeIncomingEdge(edge); - } - for (ICFGEdge* edge : rm_inedges) { - node->removeIncomingEdge(edge); - edge->getSrcNode()->removeOutgoingEdge(edge); - } - } -} +void AbstractExecution::compressICFGGraph() {} void AbstractExecution::markRecursiveFuns() { @@ -378,7 +164,7 @@ void AbstractExecution::analyse() { // handle Global ICFGNode of SVFModule if (Options::Sparse()) - compressICFGGraph(); + ICFGSimplify::simplify(_icfg); handleGlobalNode(); if (const SVFFunction* fun = _svfir->getModule()->getSVFFunction("main")) { @@ -822,7 +608,7 @@ void AbstractExecution::handleWTONode(const ICFGNode *node) std::deque worklist; if (Options::Sparse()) { - for (auto it = _subICFGNode[node].begin(); it != _subICFGNode[node].end(); ++it) { + for (auto it = ICFGSimplify::getSubICFGNode(node).begin(); it != ICFGSimplify::getSubICFGNode(node).end(); ++it) { const ICFGNode* curNode = *it; handleICFGNode(curNode); } From 8ba4f67dd6e341a53b6a85617c6e19a812aa0da9 Mon Sep 17 00:00:00 2001 From: bjjwwang Date: Mon, 26 Feb 2024 14:57:08 +1100 Subject: [PATCH 03/22] some modification --- svf/include/AE/Svfexe/AbstractExecution.h | 1 - svf/include/Util/Options.h | 2 +- svf/lib/AE/Svfexe/AbstractExecution.cpp | 4 ++-- svf/lib/Util/Options.cpp | 4 ++-- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/svf/include/AE/Svfexe/AbstractExecution.h b/svf/include/AE/Svfexe/AbstractExecution.h index ad6de2e9b..37db43ecf 100644 --- a/svf/include/AE/Svfexe/AbstractExecution.h +++ b/svf/include/AE/Svfexe/AbstractExecution.h @@ -274,7 +274,6 @@ class AbstractExecution // private data Map _preES; Map _postES; - std::string _moduleName; }; diff --git a/svf/include/Util/Options.h b/svf/include/Util/Options.h index e87bd6083..d8a374e16 100644 --- a/svf/include/Util/Options.h +++ b/svf/include/Util/Options.h @@ -273,7 +273,7 @@ class Options static const Option GepUnknownIdx; static const Option RunUncallFuncs; - static const Option Sparse; + static const Option SimplifyICFG; }; } // namespace SVF diff --git a/svf/lib/AE/Svfexe/AbstractExecution.cpp b/svf/lib/AE/Svfexe/AbstractExecution.cpp index 7eb24c9c9..c8262f0a2 100644 --- a/svf/lib/AE/Svfexe/AbstractExecution.cpp +++ b/svf/lib/AE/Svfexe/AbstractExecution.cpp @@ -163,7 +163,7 @@ void AbstractExecution::markRecursiveFuns() void AbstractExecution::analyse() { // handle Global ICFGNode of SVFModule - if (Options::Sparse()) + if (Options::SimplifyICFG()) ICFGSimplify::simplify(_icfg); handleGlobalNode(); if (const SVFFunction* fun = _svfir->getModule()->getSVFFunction("main")) @@ -607,7 +607,7 @@ void AbstractExecution::handleWTONode(const ICFGNode *node) std::deque worklist; - if (Options::Sparse()) { + if (Options::SimplifyICFG()) { for (auto it = ICFGSimplify::getSubICFGNode(node).begin(); it != ICFGSimplify::getSubICFGNode(node).end(); ++it) { const ICFGNode* curNode = *it; handleICFGNode(curNode); diff --git a/svf/lib/Util/Options.cpp b/svf/lib/Util/Options.cpp index 76dd123bb..a03599874 100644 --- a/svf/lib/Util/Options.cpp +++ b/svf/lib/Util/Options.cpp @@ -851,6 +851,6 @@ const Option Options::GepUnknownIdx( "gep-unknown-idx","Skip Gep Unknown Index",false); const Option Options::RunUncallFuncs( "run-uncall-fun","Skip Gep Unknown Index",false); -const Option Options::Sparse( - "sparse","Sparse",false); +const Option Options::SimplifyICFG( + "simplify-icfg","Simplify ICFG Graph",false); } // namespace SVF. From b3edbb27955f3cd0851295025e293eab8c012679 Mon Sep 17 00:00:00 2001 From: bjjwwang Date: Mon, 26 Feb 2024 04:38:59 +0000 Subject: [PATCH 04/22] fix some bug --- svf/lib/AE/Svfexe/AbstractExecution.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/svf/lib/AE/Svfexe/AbstractExecution.cpp b/svf/lib/AE/Svfexe/AbstractExecution.cpp index c8262f0a2..fa844ed47 100644 --- a/svf/lib/AE/Svfexe/AbstractExecution.cpp +++ b/svf/lib/AE/Svfexe/AbstractExecution.cpp @@ -144,8 +144,6 @@ AbstractExecution::~AbstractExecution() } -void AbstractExecution::compressICFGGraph() {} - void AbstractExecution::markRecursiveFuns() { // detect if callgraph has cycle From 4f0a5172b68b7a455457453a0085a14196c94383 Mon Sep 17 00:00:00 2001 From: bjjwwang Date: Mon, 26 Feb 2024 17:34:02 +1100 Subject: [PATCH 05/22] fix a bug in icfgsimplify --- svf/include/AE/Svfexe/ICFGSimplify.h | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/svf/include/AE/Svfexe/ICFGSimplify.h b/svf/include/AE/Svfexe/ICFGSimplify.h index 61522381c..90c7101de 100644 --- a/svf/include/AE/Svfexe/ICFGSimplify.h +++ b/svf/include/AE/Svfexe/ICFGSimplify.h @@ -73,8 +73,15 @@ static void simplify(ICFG* _icfg) else { const ICFGNode* pNode = bbToNodes[bb].back(); - _subICFGNode[pNode].push_back(icfgNode); - _refICFGNode[icfgNode] = pNode; + if (!SVFUtil::isa(pNode)) { + _subICFGNode[pNode].push_back(icfgNode); + _refICFGNode[icfgNode] = pNode; + } + else { + _subICFGNode[icfgNode] = {icfgNode}; + _refICFGNode[icfgNode] = icfgNode; + bbToNodes[bb].push_back(icfgNode); + } } } } @@ -251,6 +258,7 @@ static void simplify(ICFG* _icfg) edge->getSrcNode()->removeOutgoingEdge(edge); } } + _icfg->dump("cICFG"); } static const std::vector& getSubICFGNode(const ICFGNode* node) From b7ce8d2ba6dda6350c982d7c5d9ec21ba143eb6e Mon Sep 17 00:00:00 2001 From: bjjwwang Date: Mon, 26 Feb 2024 21:43:36 +1100 Subject: [PATCH 06/22] remove static functions of ICFGSimplify, add icfg simplify option --- svf/include/AE/Svfexe/AbstractExecution.h | 4 ++++ svf/include/AE/Svfexe/ICFGSimplify.h | 11 ++++++----- svf/include/Util/Options.h | 1 + svf/lib/AE/Svfexe/AbstractExecution.cpp | 11 ++++++----- svf/lib/Util/Options.cpp | 2 ++ 5 files changed, 19 insertions(+), 10 deletions(-) diff --git a/svf/include/AE/Svfexe/AbstractExecution.h b/svf/include/AE/Svfexe/AbstractExecution.h index 37db43ecf..c0f6784f2 100644 --- a/svf/include/AE/Svfexe/AbstractExecution.h +++ b/svf/include/AE/Svfexe/AbstractExecution.h @@ -35,6 +35,7 @@ #include "AE/Core/ICFGWTO.h" #include "WPA/Andersen.h" #include "Util/SVFBugReport.h" +#include "AE/Svfexe/ICFGSimplify.h" namespace SVF { @@ -276,6 +277,8 @@ class AbstractExecution Map _postES; std::string _moduleName; + ICFGSimplify* _icfg_simplify; + }; class AEAPI @@ -430,5 +433,6 @@ class AEAPI Set _checkpoints; Set _checkpoint_names; + }; } \ No newline at end of file diff --git a/svf/include/AE/Svfexe/ICFGSimplify.h b/svf/include/AE/Svfexe/ICFGSimplify.h index 90c7101de..7c5358a95 100644 --- a/svf/include/AE/Svfexe/ICFGSimplify.h +++ b/svf/include/AE/Svfexe/ICFGSimplify.h @@ -35,7 +35,7 @@ class ICFGSimplify { ICFGSimplify() = default; /// Simplify the ICFG by hiding the nodes in the same basic block -static void simplify(ICFG* _icfg) +void simplify(ICFG* _icfg) { Map> bbToNodes; for (const auto &func : *PAG::getPAG()->getModule()) @@ -258,18 +258,19 @@ static void simplify(ICFG* _icfg) edge->getSrcNode()->removeOutgoingEdge(edge); } } - _icfg->dump("cICFG"); + if (Options::DumpSimplifiedICFG()) + _icfg->dump("ICFG.simplified"); } -static const std::vector& getSubICFGNode(const ICFGNode* node) +const std::vector& getSubICFGNode(const ICFGNode* node) { return _subICFGNode[node]; } private: - static Map> _subICFGNode; - static Map _refICFGNode; + Map> _subICFGNode; + Map _refICFGNode; }; } diff --git a/svf/include/Util/Options.h b/svf/include/Util/Options.h index d8a374e16..c443adb0d 100644 --- a/svf/include/Util/Options.h +++ b/svf/include/Util/Options.h @@ -274,6 +274,7 @@ class Options static const Option RunUncallFuncs; static const Option SimplifyICFG; + static const Option DumpSimplifiedICFG; }; } // namespace SVF diff --git a/svf/lib/AE/Svfexe/AbstractExecution.cpp b/svf/lib/AE/Svfexe/AbstractExecution.cpp index fa844ed47..304e531f2 100644 --- a/svf/lib/AE/Svfexe/AbstractExecution.cpp +++ b/svf/lib/AE/Svfexe/AbstractExecution.cpp @@ -27,7 +27,6 @@ #include "WPA/Andersen.h" #include "SVFIR/SVFIR.h" #include "AE/Svfexe/AbstractExecution.h" -#include "AE/Svfexe/ICFGSimplify.h" #include "Util/Options.h" #include @@ -35,8 +34,6 @@ using namespace SVF; using namespace SVFUtil; using namespace z3; -Map> ICFGSimplify::_subICFGNode; -Map ICFGSimplify::_refICFGNode; // according to varieties of cmp insts, // maybe var X var, var X const, const X var, const X const // we accept 'var X const' 'var X var' 'const X const' @@ -162,7 +159,10 @@ void AbstractExecution::analyse() { // handle Global ICFGNode of SVFModule if (Options::SimplifyICFG()) - ICFGSimplify::simplify(_icfg); + { + _icfg_simplify = new ICFGSimplify(); + _icfg_simplify->simplify(_icfg); + } handleGlobalNode(); if (const SVFFunction* fun = _svfir->getModule()->getSVFFunction("main")) { @@ -606,7 +606,8 @@ void AbstractExecution::handleWTONode(const ICFGNode *node) std::deque worklist; if (Options::SimplifyICFG()) { - for (auto it = ICFGSimplify::getSubICFGNode(node).begin(); it != ICFGSimplify::getSubICFGNode(node).end(); ++it) { + const std::vector& worklist_vec = _icfg_simplify->getSubICFGNode(node); + for (auto it = worklist_vec.begin(); it != worklist_vec.end(); ++it) { const ICFGNode* curNode = *it; handleICFGNode(curNode); } diff --git a/svf/lib/Util/Options.cpp b/svf/lib/Util/Options.cpp index a03599874..eebd29ea9 100644 --- a/svf/lib/Util/Options.cpp +++ b/svf/lib/Util/Options.cpp @@ -853,4 +853,6 @@ const Option Options::RunUncallFuncs( "run-uncall-fun","Skip Gep Unknown Index",false); const Option Options::SimplifyICFG( "simplify-icfg","Simplify ICFG Graph",false); +const Option Options::DumpSimplifiedICFG( + "dump-simplified-icfg","Dump Simplified ICFG, filename ICFG.simplified.dot",false); } // namespace SVF. From 5c9532d54b3e4d2153fd0f7af5b507bc92999831 Mon Sep 17 00:00:00 2001 From: bjjwwang Date: Tue, 27 Feb 2024 13:35:12 +1100 Subject: [PATCH 07/22] rename and refactor --- svf-llvm/tools/AE/ae.cpp | 11 +- svf/include/AE/Svfexe/AbstractExecution.h | 13 +- svf/include/AE/Svfexe/ICFGSimplification.h | 307 +++++++++++++++++++++ svf/include/AE/Svfexe/ICFGSimplify.h | 276 ------------------ svf/include/Graphs/ICFG.h | 23 ++ svf/lib/AE/Svfexe/AbstractExecution.cpp | 26 +- 6 files changed, 351 insertions(+), 305 deletions(-) create mode 100644 svf/include/AE/Svfexe/ICFGSimplification.h delete mode 100644 svf/include/AE/Svfexe/ICFGSimplify.h diff --git a/svf-llvm/tools/AE/ae.cpp b/svf-llvm/tools/AE/ae.cpp index 5178bdaf4..9ca8a9ff3 100644 --- a/svf-llvm/tools/AE/ae.cpp +++ b/svf-llvm/tools/AE/ae.cpp @@ -653,17 +653,24 @@ int main(int argc, char** argv) AndersenWaveDiff* ander = AndersenWaveDiff::createAndersenWaveDiff(pag); PTACallGraph* callgraph = ander->getPTACallGraph(); builder.updateCallGraph(callgraph); + pag->getICFG()->updateCallGraph(callgraph); + if (Options::SimplifyICFG()) { + ICFGSimplification::simplify(pag->getICFG()); + if (Options::DumpSimplifiedICFG()) + pag->getICFG()->dump("ICFG.simplified"); + } + if (Options::BufferOverflowCheck()) { BufOverflowChecker ae; ae.initExtAPI(); - ae.runOnModule(pag); + ae.runOnModule(pag->getICFG()); } else { AbstractExecution ae; ae.initExtAPI(); - ae.runOnModule(pag); + ae.runOnModule(pag->getICFG()); } LLVMModuleSet::releaseLLVMModuleSet(); diff --git a/svf/include/AE/Svfexe/AbstractExecution.h b/svf/include/AE/Svfexe/AbstractExecution.h index c0f6784f2..a1c2d5270 100644 --- a/svf/include/AE/Svfexe/AbstractExecution.h +++ b/svf/include/AE/Svfexe/AbstractExecution.h @@ -27,15 +27,13 @@ // // Created by Jiawei Wang on 2024/1/10. // -#include -#include +#include "AE/Core/ICFGWTO.h" +#include "AE/Svfexe/ICFGSimplification.h" #include "AE/Svfexe/SVFIR2ItvExeState.h" -#include "Util/WorkList.h" #include "MSSA/SVFGBuilder.h" -#include "AE/Core/ICFGWTO.h" -#include "WPA/Andersen.h" #include "Util/SVFBugReport.h" -#include "AE/Svfexe/ICFGSimplify.h" +#include "Util/WorkList.h" +#include "WPA/Andersen.h" namespace SVF { @@ -119,7 +117,7 @@ class AbstractExecution virtual void initExtAPI(); - virtual void runOnModule(SVFIR* svfModule); + virtual void runOnModule(ICFG* icfg); /// Destructor virtual ~AbstractExecution(); @@ -277,7 +275,6 @@ class AbstractExecution Map _postES; std::string _moduleName; - ICFGSimplify* _icfg_simplify; }; diff --git a/svf/include/AE/Svfexe/ICFGSimplification.h b/svf/include/AE/Svfexe/ICFGSimplification.h new file mode 100644 index 000000000..06b4f3207 --- /dev/null +++ b/svf/include/AE/Svfexe/ICFGSimplification.h @@ -0,0 +1,307 @@ +//===- ICFGSimplification.h -- Simplify ICFG----------------------------------// +// +// SVF: Static Value-Flow Analysis +// +// Copyright (C) <2013-> +// + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. + +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +// +// The implementation is based on +// Xiao Cheng, Jiawei Wang and Yulei Sui. Precise Sparse Abstract Execution via Cross-Domain Interaction. +// 46th International Conference on Software Engineering. (ICSE24) +//===----------------------------------------------------------------------===// + + +// +// Created by Jiawei Wang on 2024/2/25. +// +#include "Graphs/ICFG.h" +#include "AE/Svfexe/SVFIR2ItvExeState.h" + + +namespace SVF +{ + +class ICFGSimplification +{ +public: +ICFGSimplification() = default; + +virtual ~ICFGSimplification() = default; + +static void simplify(ICFG* icfg) +{ + Map> bbToNodes; + Set rm_nodes; + Set simplifiedNodes; + for (const auto& func : *PAG::getPAG()->getModule()) + { + for (const auto& bb : *func) + { + for (const auto& inst : *bb) + { + if (SVFUtil::isIntrinsicInst(inst)) + continue; + const ICFGNode* icfgNode = icfg->getICFGNode(inst); + // e.g. + // block: entry + // insts: call = i32 %fun(i32 %arg) + // We put the callnode in an icfgnode alone, and the retnode is similar. + if (const CallICFGNode* callNode = + SVFUtil::dyn_cast(icfgNode)) + { + icfg->appendSubNode(callNode, callNode); + icfg->addRepNode(callNode, callNode); + bbToNodes[bb].push_back(callNode); + simplifiedNodes.insert(callNode); + + const RetICFGNode* retNode = callNode->getRetICFGNode(); + icfg->appendSubNode(retNode, retNode); + icfg->addRepNode(retNode, retNode); + bbToNodes[bb].push_back(retNode); + simplifiedNodes.insert(retNode); + } + else + { + // For ordinary instructions, we put multiple instructions in an ICFGNode + if (bbToNodes.find(bb) == bbToNodes.end()) + { + icfg->appendSubNode(icfgNode, icfgNode); + icfg->addRepNode(icfgNode, icfgNode); + bbToNodes[bb] = {icfgNode}; + simplifiedNodes.insert(icfgNode); + } + else + { + const ICFGNode* pNode = bbToNodes[bb].back(); + if (!SVFUtil::isa(pNode)) + { + icfg->appendSubNode(pNode, icfgNode); + icfg->addRepNode(icfgNode, pNode); + } + else + { + icfg->appendSubNode(icfgNode, icfgNode); + icfg->addRepNode(icfgNode, icfgNode); + bbToNodes[bb].push_back(icfgNode); + simplifiedNodes.insert(icfgNode); + } + } + } + } + } + + if (const FunEntryICFGNode* funEntryNode = + icfg->getFunEntryICFGNode(func)) + { + if (const SVFBasicBlock* bb = funEntryNode->getBB()) + { + std::vector& nodes = bbToNodes[bb]; + icfg->appendSubNode(funEntryNode, funEntryNode); + icfg->addRepNode(funEntryNode, funEntryNode); + nodes.insert(nodes.begin(), funEntryNode); + simplifiedNodes.insert(funEntryNode); + } + } + if (const FunExitICFGNode* funExitNode = icfg->getFunExitICFGNode(func)) + { + if (const SVFBasicBlock* bb = funExitNode->getBB()) + { + std::vector& nodes = bbToNodes[bb]; + icfg->appendSubNode(funExitNode, funExitNode); + icfg->addRepNode(funExitNode, funExitNode); + nodes.push_back(funExitNode); + simplifiedNodes.insert(funExitNode); + } + } + } + + for (auto &it: *icfg) { + if (simplifiedNodes.find(it.second) == simplifiedNodes.end() && + !SVFUtil::isa(it.second)) { + rm_nodes.insert(const_cast(it.second)); + } + } + + /// reconnect the ICFGNodes, + /// 1. intraCFGEdges between different basicblocks, but in the safe function e.g. entry: + /// cond = icmp eq i32 %a, 0 ---------> srcblk + /// br i1 cond, label %bb1, label %bb2 ---------> srcblk_tail + /// bb1: + /// ... --------> dstblk + /// bb2: + /// ... --------> another dstblk + /// tmpEdge is the edge between srcblk and dstblk, may have condition var (cond is true or false) + for (const auto& node : *icfg) + { + for (const auto& succ : node.second->getOutEdges()) + { + if (succ->isIntraCFGEdge()) + { + const SVFFunction* node_fun = node.second->getFun(); + const SVFFunction* succ_fun = succ->getDstNode()->getFun(); + const SVFBasicBlock* node_bb = node.second->getBB(); + const SVFBasicBlock* succ_bb = succ->getDstNode()->getBB(); + if (node_fun == succ_fun) + { + if (node_bb != succ_bb) + { + ICFGNode* srcblk = const_cast( + bbToNodes[node_bb].back()); + ICFGNode* dstblk = const_cast( + bbToNodes[succ_bb].front()); + ICFGNode* srcblk_tail = const_cast( + icfg->getSubNodes(bbToNodes[node_bb].back()).back()); + ICFGEdge* tmpEdge = + icfg->getICFGEdge(srcblk_tail, dstblk, + ICFGEdge::ICFGEdgeK::IntraCF); + IntraCFGEdge* pEdge = nullptr; + if (tmpEdge) + { + IntraCFGEdge* intraEdge = + SVFUtil::dyn_cast(tmpEdge); + pEdge = new IntraCFGEdge(srcblk, dstblk); + if (intraEdge->getCondition()) + pEdge->setBranchCondition( + intraEdge->getCondition(), + intraEdge->getSuccessorCondValue()); + } + else + { + pEdge = new IntraCFGEdge(srcblk, dstblk); + } + // avoid duplicate edges + if (srcblk->hasIncomingEdge(pEdge) || + dstblk->hasIncomingEdge(pEdge)) + continue; + else + icfg->addICFGEdge(pEdge); + } + } + } + } + } + + /// 2. intraCFGEdges in the same basicblock, but seperated by callInst + /// e.g. entry: + /// ..... --------> bbNode0 + /// call void @foo() ---------> callNode: bbNode1, retNode bbNode2 + /// ..... --------> bbNode3 + /// entry block has 4 bbNodes. the following for loop just links bbNodes in the same basic block. + for (const auto& bbNodes : bbToNodes) + { + for (u32_t i = 0; i < bbNodes.second.size() - 1; ++i) + { + ICFGNode* srcblk_tail = + const_cast(icfg->getSubNodes(bbNodes.second[i]).back()); + ICFGNode* srcblk = const_cast(bbNodes.second[i]); + ICFGNode* dstblk = const_cast(bbNodes.second[i + 1]); + if (!icfg->hasIntraICFGEdge(srcblk_tail, dstblk, + ICFGEdge::ICFGEdgeK::IntraCF)) + continue; + IntraCFGEdge* pEdge = new IntraCFGEdge(srcblk, dstblk); + if (srcblk->hasIncomingEdge(pEdge) || + dstblk->hasIncomingEdge(pEdge)) + continue; + else + icfg->addICFGEdge(pEdge); + } + } + + /// 3. CallCFGEdges and RetCFGEdges + /// CallEdge is the edge between CallNode and FunEntryNode. + /// RetEdge is the edge between FunExitNode and RetNode. + + for (const auto& bbNodes : bbToNodes) + { + for (u32_t i = 0; i < bbNodes.second.size(); ++i) + { + if (const CallICFGNode* callICFGNode = + SVFUtil::dyn_cast(bbNodes.second[i])) + { + for (const auto& icfgEdge : callICFGNode->getOutEdges()) + { + if (const CallCFGEdge* callEdge = + SVFUtil::dyn_cast(icfgEdge)) + { + ICFGNode* srcblk = + const_cast(bbNodes.second[i]); + ICFGNode* dstblk = + const_cast(callEdge->getDstNode()); + ICFGEdge* pEdge = new ICFGEdge( + srcblk, dstblk, ICFGEdge::ICFGEdgeK::CallCF); + if (srcblk->hasIncomingEdge(pEdge) || + dstblk->hasIncomingEdge(pEdge)) + continue; + else + icfg->addICFGEdge(pEdge); + } + } + } + else if (const RetICFGNode* retICFGNode = + SVFUtil::dyn_cast(bbNodes.second[i])) + { + for (const auto& icfgEdge : retICFGNode->getInEdges()) + { + if (const RetCFGEdge* retEdge = + SVFUtil::dyn_cast(icfgEdge)) + { + if (!retEdge->getSrcNode()->getFun()->hasReturn()) + continue; + ICFGNode* srcblk = + const_cast(retEdge->getSrcNode()); + ICFGNode* dstblk = + const_cast(bbNodes.second[i]); + ICFGEdge* pEdge = new ICFGEdge( + srcblk, dstblk, ICFGEdge::ICFGEdgeK::RetCF); + if (srcblk->hasIncomingEdge(pEdge) || + dstblk->hasIncomingEdge(pEdge)) + continue; + else + icfg->addICFGEdge(pEdge); + } + } + } + else + { + } + } + } + for (auto& it : rm_nodes) + { + ICFGNode* node = it; + Set rm_outedges, rm_inedges; + for (ICFGEdge* edge : node->getOutEdges()) + { + rm_outedges.insert(edge); + } + for (ICFGEdge* edge : node->getInEdges()) + { + rm_inedges.insert(edge); + } + for (ICFGEdge* edge : rm_outedges) + { + node->removeOutgoingEdge(edge); + edge->getDstNode()->removeIncomingEdge(edge); + } + for (ICFGEdge* edge : rm_inedges) + { + node->removeIncomingEdge(edge); + edge->getSrcNode()->removeOutgoingEdge(edge); + } + } +} +}; +} \ No newline at end of file diff --git a/svf/include/AE/Svfexe/ICFGSimplify.h b/svf/include/AE/Svfexe/ICFGSimplify.h deleted file mode 100644 index 7c5358a95..000000000 --- a/svf/include/AE/Svfexe/ICFGSimplify.h +++ /dev/null @@ -1,276 +0,0 @@ -//===- ICFGSimplify.h -- Simplify ICFG----------------------------------// -// -// SVF: Static Value-Flow Analysis -// -// Copyright (C) <2013-> -// - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. - -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . -// -// The implementation is based on -// Xiao Cheng, Jiawei Wang and Yulei Sui. Precise Sparse Abstract Execution via Cross-Domain Interaction. -// 46th International Conference on Software Engineering. (ICSE24) -//===----------------------------------------------------------------------===// - - -// -// Created by Jiawei Wang on 2024/2/25. -// -#include "Graphs/ICFG.h" - -namespace SVF{ -class ICFGSimplify { -public: -ICFGSimplify() = default; - -/// Simplify the ICFG by hiding the nodes in the same basic block -void simplify(ICFG* _icfg) -{ - Map> bbToNodes; - for (const auto &func : *PAG::getPAG()->getModule()) - { - for(const auto& bb: *func) - { - for(const auto& inst: *bb) - { - if(SVFUtil::isIntrinsicInst(inst)) continue; - const ICFGNode* icfgNode = _icfg->getICFGNode(inst); - // e.g. - // block: entry - // insts: call = i32 %fun(i32 %arg) - // We put the callnode in an icfgnode alone, and the retnode is similar. - if (const CallICFGNode *callNode = SVFUtil::dyn_cast(icfgNode)) - { - _refICFGNode[callNode] = callNode; - _subICFGNode[callNode] = {callNode}; - bbToNodes[bb].push_back(callNode); - - const RetICFGNode* retNode = callNode->getRetICFGNode(); - _refICFGNode[retNode] = retNode; - _subICFGNode[retNode] = {retNode}; - bbToNodes[bb].push_back(retNode); - } - else - { - // For ordinary instructions, we put multiple instructions in an ICFGNode - if (bbToNodes.find(bb) == bbToNodes.end()) - { - _subICFGNode[icfgNode] = {icfgNode}; - _refICFGNode[icfgNode] = icfgNode; - bbToNodes[bb] = {icfgNode}; - } - else - { - const ICFGNode* pNode = bbToNodes[bb].back(); - if (!SVFUtil::isa(pNode)) { - _subICFGNode[pNode].push_back(icfgNode); - _refICFGNode[icfgNode] = pNode; - } - else { - _subICFGNode[icfgNode] = {icfgNode}; - _refICFGNode[icfgNode] = icfgNode; - bbToNodes[bb].push_back(icfgNode); - } - } - } - } - } - - if (const FunEntryICFGNode* funEntryNode = _icfg->getFunEntryICFGNode(func)) - { - if(const SVFBasicBlock* bb = funEntryNode->getBB()) - { - std::vector& nodes = bbToNodes[bb]; - _subICFGNode[funEntryNode] = {funEntryNode}; - _refICFGNode[funEntryNode] = funEntryNode; - nodes.insert(nodes.begin(), funEntryNode); - } - } - if (const FunExitICFGNode* funExitNode = _icfg->getFunExitICFGNode(func)) - { - if(const SVFBasicBlock* bb = funExitNode->getBB()) - { - std::vector& nodes = bbToNodes[bb]; - _subICFGNode[funExitNode] = {funExitNode}; - _refICFGNode[funExitNode] = funExitNode; - nodes.push_back(funExitNode); - } - } - } - - Set rm_nodes; - for (auto it = _subICFGNode.begin(); it!= _subICFGNode.end(); ++it) { - for (auto it2 = it->second.begin(); it2!= it->second.end(); ++it2) { - const ICFGNode* node2 = *it2; - if (_subICFGNode.find(node2) == _subICFGNode.end()) { - rm_nodes.insert(const_cast(node2)); - } - } - } - /// reconnect the ICFGNodes, - /// 1. intraCFGEdges between different basicblocks, but in the safe function - /// e.g. entry: - /// cond = icmp eq i32 %a, 0 ---------> srcblk - /// br i1 cond, label %bb1, label %bb2 ---------> srcblk_tail - /// bb1: - /// ... --------> dstblk - /// bb2: - /// ... --------> another dstblk - /// tmpEdge is the edge between srcblk and dstblk, may have condition var (cond is true or false) - for (const auto &node : *_icfg) - { - for (const auto &succ : node.second->getOutEdges()) - { - if (succ->isIntraCFGEdge()) - { - const SVFFunction *node_fun = node.second->getFun(); - const SVFFunction *succ_fun = succ->getDstNode()->getFun(); - const SVFBasicBlock *node_bb = node.second->getBB(); - const SVFBasicBlock *succ_bb = succ->getDstNode()->getBB(); - if (node_fun == succ_fun) - { - if (node_bb != succ_bb) - { - ICFGNode* srcblk = const_cast(bbToNodes[node_bb].back()); - ICFGNode* dstblk = const_cast(bbToNodes[succ_bb].front()); - ICFGNode* srcblk_tail = const_cast(_subICFGNode[bbToNodes[node_bb].back()].back()); - ICFGEdge* tmpEdge = _icfg->getICFGEdge(srcblk_tail, dstblk, ICFGEdge::ICFGEdgeK::IntraCF); - IntraCFGEdge *pEdge = nullptr; - if (tmpEdge) { - IntraCFGEdge* intraEdge = SVFUtil::dyn_cast(tmpEdge); - pEdge = new IntraCFGEdge(srcblk, dstblk); - if (intraEdge->getCondition()) - pEdge->setBranchCondition(intraEdge->getCondition(), intraEdge->getSuccessorCondValue()); - } - else { - pEdge = new IntraCFGEdge(srcblk, dstblk); - } - // avoid duplicate edges - if (srcblk->hasIncomingEdge(pEdge) || dstblk->hasIncomingEdge(pEdge)) - continue; - else - _icfg->addICFGEdge(pEdge); - } - } - } - } - } - - /// 2. intraCFGEdges in the same basicblock, but seperated by callInst - /// e.g. entry: - /// ..... --------> bbNode0 - /// call void @foo() ---------> callNode: bbNode1, retNode bbNode2 - /// ..... --------> bbNode3 - /// entry block has 4 bbNodes. the following for loop just links bbNodes in the same basic block. - for (const auto &bbNodes : bbToNodes) - { - for (u32_t i = 0; i < bbNodes.second.size() - 1; ++i) - { - ICFGNode* srcblk_tail = const_cast(_subICFGNode[bbNodes.second[i]].back()); - ICFGNode* srcblk = const_cast(bbNodes.second[i]); - ICFGNode* dstblk = const_cast( bbNodes.second[i+1]); - if (!_icfg->hasIntraICFGEdge(srcblk_tail, dstblk, ICFGEdge::ICFGEdgeK::IntraCF)) - continue; - IntraCFGEdge *pEdge = new IntraCFGEdge(srcblk, dstblk); - if (srcblk->hasIncomingEdge(pEdge) || dstblk->hasIncomingEdge(pEdge)) - continue; - else - _icfg->addICFGEdge(pEdge); - - } - } - - /// 3. CallCFGEdges and RetCFGEdges - /// CallEdge is the edge between CallNode and FunEntryNode. - /// RetEdge is the edge between FunExitNode and RetNode. - - for (const auto &bbNodes : bbToNodes) - { - for (u32_t i = 0; i < bbNodes.second.size(); ++i) - { - if (const CallICFGNode *callICFGNode = SVFUtil::dyn_cast( - bbNodes.second[i])) - { - for (const auto &icfgEdge : callICFGNode->getOutEdges()) - { - if (const CallCFGEdge *callEdge = SVFUtil::dyn_cast(icfgEdge)) - { - ICFGNode* srcblk = const_cast(bbNodes.second[i]); - ICFGNode* dstblk = const_cast(callEdge->getDstNode()); - ICFGEdge *pEdge = new ICFGEdge(srcblk, dstblk, ICFGEdge::ICFGEdgeK::CallCF); - if (srcblk->hasIncomingEdge(pEdge) || dstblk->hasIncomingEdge(pEdge)) - continue; - else - _icfg->addICFGEdge(pEdge); - } - } - } - else if (const RetICFGNode *retICFGNode = SVFUtil::dyn_cast( - bbNodes.second[i])) - { - for (const auto &icfgEdge : retICFGNode->getInEdges()) - { - if (const RetCFGEdge *retEdge = SVFUtil::dyn_cast(icfgEdge)) - { - if(!retEdge->getSrcNode()->getFun()->hasReturn()) continue; - ICFGNode* srcblk = const_cast(retEdge->getSrcNode()); - ICFGNode* dstblk = const_cast(bbNodes.second[i]); - ICFGEdge *pEdge = new ICFGEdge(srcblk, dstblk, ICFGEdge::ICFGEdgeK::RetCF); - if (srcblk->hasIncomingEdge(pEdge) || dstblk->hasIncomingEdge(pEdge)) - continue; - else - _icfg->addICFGEdge(pEdge); - } - } - } - else - { - - } - } - } - for (auto &it : rm_nodes) { - ICFGNode* node = it; - Set rm_outedges, rm_inedges; - for (ICFGEdge* edge : node->getOutEdges()) { - rm_outedges.insert(edge); - } - for (ICFGEdge* edge : node->getInEdges()) { - rm_inedges.insert(edge); - } - for (ICFGEdge* edge : rm_outedges) { - node->removeOutgoingEdge(edge); - edge->getDstNode()->removeIncomingEdge(edge); - } - for (ICFGEdge* edge : rm_inedges) { - node->removeIncomingEdge(edge); - edge->getSrcNode()->removeOutgoingEdge(edge); - } - } - if (Options::DumpSimplifiedICFG()) - _icfg->dump("ICFG.simplified"); -} - -const std::vector& getSubICFGNode(const ICFGNode* node) -{ - return _subICFGNode[node]; -} - - -private: - Map> _subICFGNode; - Map _refICFGNode; -}; -} - diff --git a/svf/include/Graphs/ICFG.h b/svf/include/Graphs/ICFG.h index f00cd47cc..26c63cbf7 100644 --- a/svf/include/Graphs/ICFG.h +++ b/svf/include/Graphs/ICFG.h @@ -76,6 +76,9 @@ class ICFG : public GenericICFGTy GlobalICFGNode* globalBlockNode; ///< unique basic block for all globals ICFGNodeToSVFLoopVec icfgNodeToSVFLoopVec; ///< map ICFG node to the SVF loops where it resides + Map> _subNodes; /// _repNode; /// getSubNodes(const ICFGNode* node) const { + return _subNodes.find(node) == _subNodes.end()? std::vector({node}): _subNodes.at(node); + } + + virtual const ICFGNode* getRepNode(const ICFGNode* node) const { + return _repNode.find(node) == _repNode.end()? node: _repNode.at(node); + } + + virtual void appendSubNode(const ICFGNode* key, const ICFGNode* value) { + if(_subNodes.find(key) == _subNodes.end()) { + _subNodes[key] = std::vector(); + } + _subNodes[key].push_back(value); + } + + virtual void addRepNode(const ICFGNode* key, const ICFGNode* value) { + _repNode[key] = value; + } //@} private: diff --git a/svf/lib/AE/Svfexe/AbstractExecution.cpp b/svf/lib/AE/Svfexe/AbstractExecution.cpp index 304e531f2..b302e65d6 100644 --- a/svf/lib/AE/Svfexe/AbstractExecution.cpp +++ b/svf/lib/AE/Svfexe/AbstractExecution.cpp @@ -87,12 +87,12 @@ void AbstractExecution::initExtAPI() _api = new AEAPI(this, _stat); } -void AbstractExecution::runOnModule(SVF::SVFIR *svfModule) +void AbstractExecution::runOnModule(ICFG *icfg) { // 1. Start clock _stat->startClk(); - - _svfir = svfModule; + _icfg = icfg; + _svfir = PAG::getPAG(); _ander = AndersenWaveDiff::createAndersenWaveDiff(_svfir); _api->setModule(_svfir); // init SVF Execution States @@ -100,8 +100,6 @@ void AbstractExecution::runOnModule(SVF::SVFIR *svfModule) // init SSE External API Handler _callgraph = _ander->getPTACallGraph(); - _icfg = _svfir->getICFG(); - _icfg->updateCallGraph(_callgraph); /// collect checkpoint _api->collectCheckPoint(); @@ -158,11 +156,6 @@ void AbstractExecution::markRecursiveFuns() void AbstractExecution::analyse() { // handle Global ICFGNode of SVFModule - if (Options::SimplifyICFG()) - { - _icfg_simplify = new ICFGSimplify(); - _icfg_simplify->simplify(_icfg); - } handleGlobalNode(); if (const SVFFunction* fun = _svfir->getModule()->getSVFFunction("main")) { @@ -605,15 +598,10 @@ void AbstractExecution::handleWTONode(const ICFGNode *node) std::deque worklist; - if (Options::SimplifyICFG()) { - const std::vector& worklist_vec = _icfg_simplify->getSubICFGNode(node); - for (auto it = worklist_vec.begin(); it != worklist_vec.end(); ++it) { - const ICFGNode* curNode = *it; - handleICFGNode(curNode); - } - } - else { - handleICFGNode(node); + const std::vector& worklist_vec = _icfg->getSubNodes(node); + for (auto it = worklist_vec.begin(); it != worklist_vec.end(); ++it) { + const ICFGNode* curNode = *it; + handleICFGNode(curNode); } _preES.erase(node); From 58363c84ef3c7e195c555bf0db4485e4eb646109 Mon Sep 17 00:00:00 2001 From: bjjwwang Date: Tue, 27 Feb 2024 13:52:48 +1100 Subject: [PATCH 08/22] rename and refactor --- svf-llvm/tools/AE/ae.cpp | 1 + svf/include/AE/Svfexe/AbstractExecution.h | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/svf-llvm/tools/AE/ae.cpp b/svf-llvm/tools/AE/ae.cpp index 9ca8a9ff3..948a32eb5 100644 --- a/svf-llvm/tools/AE/ae.cpp +++ b/svf-llvm/tools/AE/ae.cpp @@ -29,6 +29,7 @@ #include "WPA/WPAPass.h" #include "Util/CommandLine.h" #include "Util/Options.h" +#include "AE/Svfexe/ICFGSimplification.h" #include "AE/Svfexe/BufOverflowChecker.h" #include "AE/Core/RelExeState.h" diff --git a/svf/include/AE/Svfexe/AbstractExecution.h b/svf/include/AE/Svfexe/AbstractExecution.h index a1c2d5270..6e22d48a6 100644 --- a/svf/include/AE/Svfexe/AbstractExecution.h +++ b/svf/include/AE/Svfexe/AbstractExecution.h @@ -28,7 +28,6 @@ // Created by Jiawei Wang on 2024/1/10. // #include "AE/Core/ICFGWTO.h" -#include "AE/Svfexe/ICFGSimplification.h" #include "AE/Svfexe/SVFIR2ItvExeState.h" #include "MSSA/SVFGBuilder.h" #include "Util/SVFBugReport.h" From 8c8a8847a500d7a1076e05ad179c0eac41a0fdf4 Mon Sep 17 00:00:00 2001 From: bjjwwang Date: Tue, 27 Feb 2024 15:03:09 +1100 Subject: [PATCH 09/22] rename and refactor --- svf-llvm/tools/AE/ae.cpp | 7 +++---- svf/include/AE/Svfexe/AbstractExecution.h | 23 ++++++++++++++++------ svf/include/AE/Svfexe/ICFGSimplification.h | 2 +- svf/include/Util/Options.h | 3 +-- svf/lib/AE/Svfexe/AbstractExecution.cpp | 17 +++++++++------- svf/lib/AE/Svfexe/BufOverflowChecker.cpp | 6 ++++-- svf/lib/Util/Options.cpp | 6 ++---- 7 files changed, 38 insertions(+), 26 deletions(-) diff --git a/svf-llvm/tools/AE/ae.cpp b/svf-llvm/tools/AE/ae.cpp index 948a32eb5..501980d47 100644 --- a/svf-llvm/tools/AE/ae.cpp +++ b/svf-llvm/tools/AE/ae.cpp @@ -30,6 +30,7 @@ #include "Util/CommandLine.h" #include "Util/Options.h" #include "AE/Svfexe/ICFGSimplification.h" +#include "WPA/Andersen.h" #include "AE/Svfexe/BufOverflowChecker.h" #include "AE/Core/RelExeState.h" @@ -655,10 +656,8 @@ int main(int argc, char** argv) PTACallGraph* callgraph = ander->getPTACallGraph(); builder.updateCallGraph(callgraph); pag->getICFG()->updateCallGraph(callgraph); - if (Options::SimplifyICFG()) { - ICFGSimplification::simplify(pag->getICFG()); - if (Options::DumpSimplifiedICFG()) - pag->getICFG()->dump("ICFG.simplified"); + if (Options::ICFGMergeAdjacentNodes()) { + ICFGSimplification::mergeAdjacentNodes(pag->getICFG()); } if (Options::BufferOverflowCheck()) diff --git a/svf/include/AE/Svfexe/AbstractExecution.h b/svf/include/AE/Svfexe/AbstractExecution.h index 6e22d48a6..1676b70bc 100644 --- a/svf/include/AE/Svfexe/AbstractExecution.h +++ b/svf/include/AE/Svfexe/AbstractExecution.h @@ -27,11 +27,8 @@ // // Created by Jiawei Wang on 2024/1/10. // -#include "AE/Core/ICFGWTO.h" -#include "AE/Svfexe/SVFIR2ItvExeState.h" -#include "MSSA/SVFGBuilder.h" + #include "Util/SVFBugReport.h" -#include "Util/WorkList.h" #include "WPA/Andersen.h" namespace SVF @@ -39,6 +36,22 @@ namespace SVF class AbstractExecution; class AEStat; class AEAPI; +class SVFIR2ItvExeState; +class IntervalValue; +class IntervalExeState; +class ExeState; +class ICFGWTO; +template class WTONode; +template class WTOCycle; +template<> class WTONode; +template<> class WTOCycle; +typedef WTOCycle ICFGWTOCycle; +typedef WTONode ICFGWTONode; + +template class FILOWorkList; + + + enum class AEKind @@ -280,8 +293,6 @@ class AbstractExecution class AEAPI { public: - - typedef ExeState::Addrs Addrs; enum ExtAPIType { UNCLASSIFIED, MEMCPY, MEMSET, STRCPY, STRCAT }; static bool classof(const AEAPI* api) { diff --git a/svf/include/AE/Svfexe/ICFGSimplification.h b/svf/include/AE/Svfexe/ICFGSimplification.h index 06b4f3207..909e7e268 100644 --- a/svf/include/AE/Svfexe/ICFGSimplification.h +++ b/svf/include/AE/Svfexe/ICFGSimplification.h @@ -41,7 +41,7 @@ ICFGSimplification() = default; virtual ~ICFGSimplification() = default; -static void simplify(ICFG* icfg) +static void mergeAdjacentNodes(ICFG* icfg) { Map> bbToNodes; Set rm_nodes; diff --git a/svf/include/Util/Options.h b/svf/include/Util/Options.h index c443adb0d..e7cd79053 100644 --- a/svf/include/Util/Options.h +++ b/svf/include/Util/Options.h @@ -273,8 +273,7 @@ class Options static const Option GepUnknownIdx; static const Option RunUncallFuncs; - static const Option SimplifyICFG; - static const Option DumpSimplifiedICFG; + static const Option ICFGMergeAdjacentNodes; }; } // namespace SVF diff --git a/svf/lib/AE/Svfexe/AbstractExecution.cpp b/svf/lib/AE/Svfexe/AbstractExecution.cpp index b302e65d6..0c0f4c3c1 100644 --- a/svf/lib/AE/Svfexe/AbstractExecution.cpp +++ b/svf/lib/AE/Svfexe/AbstractExecution.cpp @@ -24,9 +24,12 @@ // // Created by Jiawei Wang on 2024/1/10. // -#include "WPA/Andersen.h" + +#include "AE/Core/ICFGWTO.h" +#include "Util/WorkList.h" #include "SVFIR/SVFIR.h" #include "AE/Svfexe/AbstractExecution.h" +#include "AE/Svfexe/SVFIR2ItvExeState.h" #include "Util/Options.h" #include @@ -1216,7 +1219,7 @@ std::string AEAPI::strRead(const SVFValue* rhs) { // dead loop for string and break if there's a \0. If no \0, it will throw err. if (!es.inVarToAddrsTable(_svfir->getValueNode(rhs))) continue; - Addrs expr0 = _ae->_svfir2ExeState->getGepObjAddress(_svfir->getValueNode(rhs), index); + ExeState::Addrs expr0 = _ae->_svfir2ExeState->getGepObjAddress(_svfir->getValueNode(rhs), index); IntervalValue val = IntervalValue::bottom(); for (const auto &addr: expr0) { @@ -1526,7 +1529,7 @@ IntervalValue AEAPI::getStrlen(const SVF::SVFValue *strValue) { for (u32_t index = 0; index < dst_size.lb().getNumeral(); index++) { - Addrs expr0 = _ae->_svfir2ExeState->getGepObjAddress(dstid, index); + ExeState::Addrs expr0 = _ae->_svfir2ExeState->getGepObjAddress(dstid, index); IntervalValue val = IntervalValue::bottom(); for (const auto &addr: expr0) { @@ -1641,8 +1644,8 @@ void AEAPI::handleMemcpy(const SVF::SVFValue *dst, const SVF::SVFValue *src, SVF for (u32_t index = 0; index < range_val; index++) { // dead loop for string and break if there's a \0. If no \0, it will throw err. - Addrs expr_src = _ae->_svfir2ExeState->getGepObjAddress(srcId, index); - Addrs expr_dst = _ae->_svfir2ExeState->getGepObjAddress(dstId, index + start_idx); + ExeState::Addrs expr_src = _ae->_svfir2ExeState->getGepObjAddress(srcId, index); + ExeState::Addrs expr_dst = _ae->_svfir2ExeState->getGepObjAddress(dstId, index + start_idx); for (const auto &dst: expr_dst) { for (const auto &src: expr_src) @@ -1667,7 +1670,7 @@ const SVFType* AEAPI::getPointeeElement(NodeID id) assert(_ae->_svfir2ExeState->inVarToAddrsTable(id) && "id is not in varToAddrsTable"); if (_ae->_svfir2ExeState->inVarToAddrsTable(id)) { - const Addrs& addrs = _ae->_svfir2ExeState->getAddrs(id); + const ExeState::Addrs& addrs = _ae->_svfir2ExeState->getAddrs(id); for (auto addr: addrs) { NodeID addr_id = _ae->_svfir2ExeState->getInternalID(addr); @@ -1711,7 +1714,7 @@ void AEAPI::handleMemset(const SVF::SVFValue *dst, SVF::IntervalValue elem, SVF: // dead loop for string and break if there's a \0. If no \0, it will throw err. if (_ae->_svfir2ExeState->inVarToAddrsTable(dstId)) { - Addrs lhs_gep = _ae->_svfir2ExeState->getGepObjAddress(dstId, index); + ExeState::Addrs lhs_gep = _ae->_svfir2ExeState->getGepObjAddress(dstId, index); for (const auto &addr: lhs_gep) { u32_t objId = ExeState::getInternalID(addr); diff --git a/svf/lib/AE/Svfexe/BufOverflowChecker.cpp b/svf/lib/AE/Svfexe/BufOverflowChecker.cpp index 77f729b61..4c2268df6 100644 --- a/svf/lib/AE/Svfexe/BufOverflowChecker.cpp +++ b/svf/lib/AE/Svfexe/BufOverflowChecker.cpp @@ -26,6 +26,8 @@ // #include "AE/Svfexe/BufOverflowChecker.h" +#include "AE/Svfexe/SVFIR2ItvExeState.h" +#include "Util/WorkList.h" #include "SVFIR/SVFType.h" #include "Util/Options.h" #include @@ -148,7 +150,7 @@ void BufOverflowCheckerAPI::initExtFunMap() } else { - Addrs Addrs = ae->_svfir2ExeState->getAddrs(dst_id); + ExeState::Addrs Addrs = ae->_svfir2ExeState->getAddrs(dst_id); for (auto vaddr: Addrs) { u32_t objId = ae->_svfir2ExeState->getInternalID(vaddr); @@ -172,7 +174,7 @@ void BufOverflowCheckerAPI::initExtFunMap() } else { - Addrs Addrs = ae->_svfir2ExeState->getAddrs(dst_id); + ExeState::Addrs Addrs = ae->_svfir2ExeState->getAddrs(dst_id); for (auto vaddr: Addrs) { u32_t objId = ae->_svfir2ExeState->getInternalID(vaddr); diff --git a/svf/lib/Util/Options.cpp b/svf/lib/Util/Options.cpp index eebd29ea9..599d9c08c 100644 --- a/svf/lib/Util/Options.cpp +++ b/svf/lib/Util/Options.cpp @@ -851,8 +851,6 @@ const Option Options::GepUnknownIdx( "gep-unknown-idx","Skip Gep Unknown Index",false); const Option Options::RunUncallFuncs( "run-uncall-fun","Skip Gep Unknown Index",false); -const Option Options::SimplifyICFG( - "simplify-icfg","Simplify ICFG Graph",false); -const Option Options::DumpSimplifiedICFG( - "dump-simplified-icfg","Dump Simplified ICFG, filename ICFG.simplified.dot",false); +const Option Options::ICFGMergeAdjacentNodes( + "icfg-merge-adjnodes","ICFG Simplification - Merge Adjacent Nodes in the Same Basic Block.",false); } // namespace SVF. From 926532a7188e96981b05b78d66c8ad4f64afd46b Mon Sep 17 00:00:00 2001 From: bjjwwang Date: Tue, 27 Feb 2024 20:01:04 +1100 Subject: [PATCH 10/22] move include ICFGWTO.h from cpp to h --- svf/include/AE/Svfexe/AbstractExecution.h | 8 +------- svf/lib/AE/Svfexe/AbstractExecution.cpp | 1 - 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/svf/include/AE/Svfexe/AbstractExecution.h b/svf/include/AE/Svfexe/AbstractExecution.h index 1676b70bc..05b1f0ae5 100644 --- a/svf/include/AE/Svfexe/AbstractExecution.h +++ b/svf/include/AE/Svfexe/AbstractExecution.h @@ -29,6 +29,7 @@ // #include "Util/SVFBugReport.h" +#include "AE/Core/ICFGWTO.h" #include "WPA/Andersen.h" namespace SVF @@ -40,13 +41,6 @@ class SVFIR2ItvExeState; class IntervalValue; class IntervalExeState; class ExeState; -class ICFGWTO; -template class WTONode; -template class WTOCycle; -template<> class WTONode; -template<> class WTOCycle; -typedef WTOCycle ICFGWTOCycle; -typedef WTONode ICFGWTONode; template class FILOWorkList; diff --git a/svf/lib/AE/Svfexe/AbstractExecution.cpp b/svf/lib/AE/Svfexe/AbstractExecution.cpp index 0c0f4c3c1..d3694d1d3 100644 --- a/svf/lib/AE/Svfexe/AbstractExecution.cpp +++ b/svf/lib/AE/Svfexe/AbstractExecution.cpp @@ -25,7 +25,6 @@ // Created by Jiawei Wang on 2024/1/10. // -#include "AE/Core/ICFGWTO.h" #include "Util/WorkList.h" #include "SVFIR/SVFIR.h" #include "AE/Svfexe/AbstractExecution.h" From 1b13e2118da7aac6dc7bcdd1d093be443772f322 Mon Sep 17 00:00:00 2001 From: bjjwwang Date: Tue, 27 Feb 2024 20:04:49 +1100 Subject: [PATCH 11/22] move include ICFGWTO.h from cpp to h --- svf/include/AE/Svfexe/AbstractExecution.h | 3 +-- svf/lib/AE/Svfexe/AbstractExecution.cpp | 1 - svf/lib/AE/Svfexe/BufOverflowChecker.cpp | 1 - 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/svf/include/AE/Svfexe/AbstractExecution.h b/svf/include/AE/Svfexe/AbstractExecution.h index 05b1f0ae5..e7d0ac6f1 100644 --- a/svf/include/AE/Svfexe/AbstractExecution.h +++ b/svf/include/AE/Svfexe/AbstractExecution.h @@ -31,15 +31,14 @@ #include "Util/SVFBugReport.h" #include "AE/Core/ICFGWTO.h" #include "WPA/Andersen.h" +#include "AE/Svfexe/SVFIR2ItvExeState.h" namespace SVF { class AbstractExecution; class AEStat; class AEAPI; -class SVFIR2ItvExeState; class IntervalValue; -class IntervalExeState; class ExeState; template class FILOWorkList; diff --git a/svf/lib/AE/Svfexe/AbstractExecution.cpp b/svf/lib/AE/Svfexe/AbstractExecution.cpp index d3694d1d3..86f2a05c0 100644 --- a/svf/lib/AE/Svfexe/AbstractExecution.cpp +++ b/svf/lib/AE/Svfexe/AbstractExecution.cpp @@ -28,7 +28,6 @@ #include "Util/WorkList.h" #include "SVFIR/SVFIR.h" #include "AE/Svfexe/AbstractExecution.h" -#include "AE/Svfexe/SVFIR2ItvExeState.h" #include "Util/Options.h" #include diff --git a/svf/lib/AE/Svfexe/BufOverflowChecker.cpp b/svf/lib/AE/Svfexe/BufOverflowChecker.cpp index 4c2268df6..f4e9ee1d2 100644 --- a/svf/lib/AE/Svfexe/BufOverflowChecker.cpp +++ b/svf/lib/AE/Svfexe/BufOverflowChecker.cpp @@ -26,7 +26,6 @@ // #include "AE/Svfexe/BufOverflowChecker.h" -#include "AE/Svfexe/SVFIR2ItvExeState.h" #include "Util/WorkList.h" #include "SVFIR/SVFType.h" #include "Util/Options.h" From 5210decdf93db62f8b4e86f5dd350dcacc46c710 Mon Sep 17 00:00:00 2001 From: bjjwwang Date: Tue, 27 Feb 2024 21:36:54 +1100 Subject: [PATCH 12/22] solve asan problem --- svf/include/AE/Svfexe/ICFGSimplification.h | 6 ++---- svf/include/Graphs/ICFG.h | 6 ++++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/svf/include/AE/Svfexe/ICFGSimplification.h b/svf/include/AE/Svfexe/ICFGSimplification.h index 909e7e268..5cc8890ac 100644 --- a/svf/include/AE/Svfexe/ICFGSimplification.h +++ b/svf/include/AE/Svfexe/ICFGSimplification.h @@ -293,13 +293,11 @@ static void mergeAdjacentNodes(ICFG* icfg) } for (ICFGEdge* edge : rm_outedges) { - node->removeOutgoingEdge(edge); - edge->getDstNode()->removeIncomingEdge(edge); + icfg->removeICFGEdge(edge); } for (ICFGEdge* edge : rm_inedges) { - node->removeIncomingEdge(edge); - edge->getSrcNode()->removeOutgoingEdge(edge); + icfg->removeICFGEdge(edge); } } } diff --git a/svf/include/Graphs/ICFG.h b/svf/include/Graphs/ICFG.h index 26c63cbf7..5dfe3398c 100644 --- a/svf/include/Graphs/ICFG.h +++ b/svf/include/Graphs/ICFG.h @@ -160,14 +160,16 @@ class ICFG : public GenericICFGTy return all_added; } -protected: - /// Remove a SVFG edge + /// Remove a ICFG edge inline void removeICFGEdge(ICFGEdge* edge) { edge->getDstNode()->removeIncomingEdge(edge); edge->getSrcNode()->removeOutgoingEdge(edge); delete edge; } + +protected: + /// Remove a ICFGNode inline void removeICFGNode(ICFGNode* node) { From 53318d82348f57d28d3668deb24e30bf511e6301 Mon Sep 17 00:00:00 2001 From: bjjwwang Date: Tue, 27 Feb 2024 22:36:34 +1100 Subject: [PATCH 13/22] solve asan problem --- svf/include/AE/Svfexe/ICFGSimplification.h | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/svf/include/AE/Svfexe/ICFGSimplification.h b/svf/include/AE/Svfexe/ICFGSimplification.h index 5cc8890ac..a6f282ac3 100644 --- a/svf/include/AE/Svfexe/ICFGSimplification.h +++ b/svf/include/AE/Svfexe/ICFGSimplification.h @@ -185,7 +185,10 @@ static void mergeAdjacentNodes(ICFG* icfg) // avoid duplicate edges if (srcblk->hasIncomingEdge(pEdge) || dstblk->hasIncomingEdge(pEdge)) + { + delete pEdge; continue; + } else icfg->addICFGEdge(pEdge); } @@ -213,8 +216,10 @@ static void mergeAdjacentNodes(ICFG* icfg) continue; IntraCFGEdge* pEdge = new IntraCFGEdge(srcblk, dstblk); if (srcblk->hasIncomingEdge(pEdge) || - dstblk->hasIncomingEdge(pEdge)) + dstblk->hasIncomingEdge(pEdge)) { + delete pEdge; continue; + } else icfg->addICFGEdge(pEdge); } @@ -244,7 +249,10 @@ static void mergeAdjacentNodes(ICFG* icfg) srcblk, dstblk, ICFGEdge::ICFGEdgeK::CallCF); if (srcblk->hasIncomingEdge(pEdge) || dstblk->hasIncomingEdge(pEdge)) + { + delete pEdge; continue; + } else icfg->addICFGEdge(pEdge); } @@ -268,7 +276,10 @@ static void mergeAdjacentNodes(ICFG* icfg) srcblk, dstblk, ICFGEdge::ICFGEdgeK::RetCF); if (srcblk->hasIncomingEdge(pEdge) || dstblk->hasIncomingEdge(pEdge)) + { + delete pEdge; continue; + } else icfg->addICFGEdge(pEdge); } From 5e877ca69ccd84ec093f5fc87092f534b8df7d51 Mon Sep 17 00:00:00 2001 From: bjjwwang Date: Tue, 27 Feb 2024 23:06:23 +1100 Subject: [PATCH 14/22] solve asan problem --- svf/include/AE/Svfexe/ICFGSimplification.h | 77 +++++++++++----------- 1 file changed, 38 insertions(+), 39 deletions(-) diff --git a/svf/include/AE/Svfexe/ICFGSimplification.h b/svf/include/AE/Svfexe/ICFGSimplification.h index a6f282ac3..d058986ac 100644 --- a/svf/include/AE/Svfexe/ICFGSimplification.h +++ b/svf/include/AE/Svfexe/ICFGSimplification.h @@ -168,29 +168,25 @@ static void mergeAdjacentNodes(ICFG* icfg) icfg->getICFGEdge(srcblk_tail, dstblk, ICFGEdge::ICFGEdgeK::IntraCF); IntraCFGEdge* pEdge = nullptr; - if (tmpEdge) - { - IntraCFGEdge* intraEdge = - SVFUtil::dyn_cast(tmpEdge); - pEdge = new IntraCFGEdge(srcblk, dstblk); - if (intraEdge->getCondition()) - pEdge->setBranchCondition( - intraEdge->getCondition(), - intraEdge->getSuccessorCondValue()); - } - else - { - pEdge = new IntraCFGEdge(srcblk, dstblk); - } - // avoid duplicate edges - if (srcblk->hasIncomingEdge(pEdge) || - dstblk->hasIncomingEdge(pEdge)) - { - delete pEdge; + if (icfg->hasIntraICFGEdge(srcblk, dstblk, ICFGEdge::ICFGEdgeK::IntraCF)) { continue; - } - else + } else { + if (tmpEdge) + { + IntraCFGEdge* intraEdge = + SVFUtil::dyn_cast(tmpEdge); + pEdge = new IntraCFGEdge(srcblk, dstblk); + if (intraEdge->getCondition()) + pEdge->setBranchCondition( + intraEdge->getCondition(), + intraEdge->getSuccessorCondValue()); + } + else + { + pEdge = new IntraCFGEdge(srcblk, dstblk); + } icfg->addICFGEdge(pEdge); + } } } } @@ -213,15 +209,20 @@ static void mergeAdjacentNodes(ICFG* icfg) ICFGNode* dstblk = const_cast(bbNodes.second[i + 1]); if (!icfg->hasIntraICFGEdge(srcblk_tail, dstblk, ICFGEdge::ICFGEdgeK::IntraCF)) + { continue; - IntraCFGEdge* pEdge = new IntraCFGEdge(srcblk, dstblk); - if (srcblk->hasIncomingEdge(pEdge) || - dstblk->hasIncomingEdge(pEdge)) { - delete pEdge; + } + + if (icfg->hasIntraICFGEdge(srcblk, dstblk, + ICFGEdge::ICFGEdgeK::IntraCF)) + { continue; } else + { + IntraCFGEdge* pEdge = new IntraCFGEdge(srcblk, dstblk); icfg->addICFGEdge(pEdge); + } } } @@ -245,16 +246,15 @@ static void mergeAdjacentNodes(ICFG* icfg) const_cast(bbNodes.second[i]); ICFGNode* dstblk = const_cast(callEdge->getDstNode()); - ICFGEdge* pEdge = new ICFGEdge( - srcblk, dstblk, ICFGEdge::ICFGEdgeK::CallCF); - if (srcblk->hasIncomingEdge(pEdge) || - dstblk->hasIncomingEdge(pEdge)) - { - delete pEdge; + if (icfg->hasIntraICFGEdge(srcblk, dstblk, + ICFGEdge::ICFGEdgeK::CallCF)) continue; - } else + { + ICFGEdge* pEdge = new ICFGEdge( + srcblk, dstblk, ICFGEdge::ICFGEdgeK::CallCF); icfg->addICFGEdge(pEdge); + } } } } @@ -272,16 +272,15 @@ static void mergeAdjacentNodes(ICFG* icfg) const_cast(retEdge->getSrcNode()); ICFGNode* dstblk = const_cast(bbNodes.second[i]); - ICFGEdge* pEdge = new ICFGEdge( - srcblk, dstblk, ICFGEdge::ICFGEdgeK::RetCF); - if (srcblk->hasIncomingEdge(pEdge) || - dstblk->hasIncomingEdge(pEdge)) - { - delete pEdge; + if (icfg->hasIntraICFGEdge(srcblk, dstblk, + ICFGEdge::ICFGEdgeK::RetCF)) continue; - } else + { + ICFGEdge* pEdge = new ICFGEdge( + srcblk, dstblk, ICFGEdge::ICFGEdgeK::RetCF); icfg->addICFGEdge(pEdge); + } } } } From ef1416cdc1c57da6b389e8528a7f8cc04d2c8644 Mon Sep 17 00:00:00 2001 From: bjjwwang Date: Tue, 27 Feb 2024 23:32:49 +1100 Subject: [PATCH 15/22] solve asan problem --- svf/include/AE/Svfexe/ICFGSimplification.h | 22 +++++---------- svf/include/Graphs/ICFG.h | 33 +++++++++++----------- 2 files changed, 23 insertions(+), 32 deletions(-) diff --git a/svf/include/AE/Svfexe/ICFGSimplification.h b/svf/include/AE/Svfexe/ICFGSimplification.h index d058986ac..f2d626801 100644 --- a/svf/include/AE/Svfexe/ICFGSimplification.h +++ b/svf/include/AE/Svfexe/ICFGSimplification.h @@ -167,7 +167,6 @@ static void mergeAdjacentNodes(ICFG* icfg) ICFGEdge* tmpEdge = icfg->getICFGEdge(srcblk_tail, dstblk, ICFGEdge::ICFGEdgeK::IntraCF); - IntraCFGEdge* pEdge = nullptr; if (icfg->hasIntraICFGEdge(srcblk, dstblk, ICFGEdge::ICFGEdgeK::IntraCF)) { continue; } else { @@ -175,17 +174,15 @@ static void mergeAdjacentNodes(ICFG* icfg) { IntraCFGEdge* intraEdge = SVFUtil::dyn_cast(tmpEdge); - pEdge = new IntraCFGEdge(srcblk, dstblk); if (intraEdge->getCondition()) - pEdge->setBranchCondition( - intraEdge->getCondition(), - intraEdge->getSuccessorCondValue()); + icfg->addConditionalIntraEdge(srcblk, dstblk, intraEdge->getCondition(), intraEdge->getSuccessorCondValue()); + else + icfg->addIntraEdge(srcblk, dstblk); } else { - pEdge = new IntraCFGEdge(srcblk, dstblk); + icfg->addIntraEdge(srcblk, dstblk); } - icfg->addICFGEdge(pEdge); } } } @@ -220,8 +217,7 @@ static void mergeAdjacentNodes(ICFG* icfg) } else { - IntraCFGEdge* pEdge = new IntraCFGEdge(srcblk, dstblk); - icfg->addICFGEdge(pEdge); + icfg->addIntraEdge(srcblk, dstblk); } } } @@ -251,9 +247,7 @@ static void mergeAdjacentNodes(ICFG* icfg) continue; else { - ICFGEdge* pEdge = new ICFGEdge( - srcblk, dstblk, ICFGEdge::ICFGEdgeK::CallCF); - icfg->addICFGEdge(pEdge); + icfg->addCallEdge(srcblk, dstblk, callICFGNode->getCallSite()); } } } @@ -277,9 +271,7 @@ static void mergeAdjacentNodes(ICFG* icfg) continue; else { - ICFGEdge* pEdge = new ICFGEdge( - srcblk, dstblk, ICFGEdge::ICFGEdgeK::RetCF); - icfg->addICFGEdge(pEdge); + icfg->addRetEdge(srcblk, dstblk, retICFGNode->getCallSite()); } } } diff --git a/svf/include/Graphs/ICFG.h b/svf/include/Graphs/ICFG.h index 5dfe3398c..0a3b792c6 100644 --- a/svf/include/Graphs/ICFG.h +++ b/svf/include/Graphs/ICFG.h @@ -150,16 +150,13 @@ class ICFG : public GenericICFGTy return icfgNodeToSVFLoopVec; } - /// Add ICFG edge - inline bool addICFGEdge(ICFGEdge* edge) - { - bool added1 = edge->getDstNode()->addIncomingEdge(edge); - bool added2 = edge->getSrcNode()->addOutgoingEdge(edge); - bool all_added = added1 && added2; - assert(all_added && "ICFGEdge not added?"); - return all_added; - } - + /// Add control-flow edges for top level pointers + //@{ + ICFGEdge* addIntraEdge(ICFGNode* srcNode, ICFGNode* dstNode); + ICFGEdge* addConditionalIntraEdge(ICFGNode* srcNode, ICFGNode* dstNode, const SVFValue* condition, s32_t branchCondVal); + ICFGEdge* addCallEdge(ICFGNode* srcNode, ICFGNode* dstNode, const SVFInstruction* cs); + ICFGEdge* addRetEdge(ICFGNode* srcNode, ICFGNode* dstNode, const SVFInstruction* cs); + //@} /// Remove a ICFG edge inline void removeICFGEdge(ICFGEdge* edge) { @@ -176,13 +173,15 @@ class ICFG : public GenericICFGTy removeGNode(node); } - /// Add control-flow edges for top level pointers - //@{ - ICFGEdge* addIntraEdge(ICFGNode* srcNode, ICFGNode* dstNode); - ICFGEdge* addConditionalIntraEdge(ICFGNode* srcNode, ICFGNode* dstNode, const SVFValue* condition, s32_t branchCondVal); - ICFGEdge* addCallEdge(ICFGNode* srcNode, ICFGNode* dstNode, const SVFInstruction* cs); - ICFGEdge* addRetEdge(ICFGNode* srcNode, ICFGNode* dstNode, const SVFInstruction* cs); - //@} + /// Add ICFG edge + inline bool addICFGEdge(ICFGEdge* edge) + { + bool added1 = edge->getDstNode()->addIncomingEdge(edge); + bool added2 = edge->getSrcNode()->addOutgoingEdge(edge); + bool all_added = added1 && added2; + assert(all_added && "ICFGEdge not added?"); + return all_added; + } /// sanitize Intra edges, verify that both nodes belong to the same function. inline void checkIntraEdgeParents(const ICFGNode *srcNode, const ICFGNode *dstNode) From 9872fd30da9eff7a54c68cf4b468cf182336f65e Mon Sep 17 00:00:00 2001 From: bjjwwang Date: Tue, 27 Feb 2024 23:48:28 +1100 Subject: [PATCH 16/22] move addICFGEdges functions to protected --- svf/include/Graphs/ICFG.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/svf/include/Graphs/ICFG.h b/svf/include/Graphs/ICFG.h index 0a3b792c6..667f9b61d 100644 --- a/svf/include/Graphs/ICFG.h +++ b/svf/include/Graphs/ICFG.h @@ -49,6 +49,7 @@ class ICFG : public GenericICFGTy friend class ICFGBuilder; friend class SVFIRWriter; friend class SVFIRReader; + friend class ICFGSimplification; public: @@ -150,6 +151,7 @@ class ICFG : public GenericICFGTy return icfgNodeToSVFLoopVec; } +protected: /// Add control-flow edges for top level pointers //@{ ICFGEdge* addIntraEdge(ICFGNode* srcNode, ICFGNode* dstNode); @@ -165,8 +167,6 @@ class ICFG : public GenericICFGTy delete edge; } -protected: - /// Remove a ICFGNode inline void removeICFGNode(ICFGNode* node) { From c83383b74d1d1096f6328146340993b20c9182c3 Mon Sep 17 00:00:00 2001 From: bjjwwang Date: Tue, 27 Feb 2024 23:52:03 +1100 Subject: [PATCH 17/22] move addICFGEdge to private --- svf/include/Graphs/ICFG.h | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/svf/include/Graphs/ICFG.h b/svf/include/Graphs/ICFG.h index 667f9b61d..20b6071f7 100644 --- a/svf/include/Graphs/ICFG.h +++ b/svf/include/Graphs/ICFG.h @@ -173,16 +173,6 @@ class ICFG : public GenericICFGTy removeGNode(node); } - /// Add ICFG edge - inline bool addICFGEdge(ICFGEdge* edge) - { - bool added1 = edge->getDstNode()->addIncomingEdge(edge); - bool added2 = edge->getSrcNode()->addOutgoingEdge(edge); - bool all_added = added1 && added2; - assert(all_added && "ICFGEdge not added?"); - return all_added; - } - /// sanitize Intra edges, verify that both nodes belong to the same function. inline void checkIntraEdgeParents(const ICFGNode *srcNode, const ICFGNode *dstNode) { @@ -248,6 +238,15 @@ class ICFG : public GenericICFGTy //@} private: + /// Add ICFG edge, only used by addIntraEdge, addCallEdge, addRetEdge etc. + inline bool addICFGEdge(ICFGEdge* edge) + { + bool added1 = edge->getDstNode()->addIncomingEdge(edge); + bool added2 = edge->getSrcNode()->addOutgoingEdge(edge); + bool all_added = added1 && added2; + assert(all_added && "ICFGEdge not added?"); + return all_added; + } /// Get/Add IntraBlock ICFGNode inline IntraICFGNode* getIntraBlock(const SVFInstruction* inst) From 191187a1fb3965bd74376b152497cf183804a18f Mon Sep 17 00:00:00 2001 From: bjjwwang Date: Wed, 28 Feb 2024 22:13:38 +1100 Subject: [PATCH 18/22] refactor the algorithm --- svf/include/AE/Svfexe/ICFGSimplification.h | 248 +++++---------------- svf/include/Graphs/ICFG.h | 25 ++- 2 files changed, 70 insertions(+), 203 deletions(-) diff --git a/svf/include/AE/Svfexe/ICFGSimplification.h b/svf/include/AE/Svfexe/ICFGSimplification.h index f2d626801..c048b3dc0 100644 --- a/svf/include/AE/Svfexe/ICFGSimplification.h +++ b/svf/include/AE/Svfexe/ICFGSimplification.h @@ -44,8 +44,7 @@ virtual ~ICFGSimplification() = default; static void mergeAdjacentNodes(ICFG* icfg) { Map> bbToNodes; - Set rm_nodes; - Set simplifiedNodes; + Set subNodes; for (const auto& func : *PAG::getPAG()->getModule()) { for (const auto& bb : *func) @@ -62,57 +61,52 @@ static void mergeAdjacentNodes(ICFG* icfg) if (const CallICFGNode* callNode = SVFUtil::dyn_cast(icfgNode)) { - icfg->appendSubNode(callNode, callNode); - icfg->addRepNode(callNode, callNode); - bbToNodes[bb].push_back(callNode); - simplifiedNodes.insert(callNode); + subNodes.insert(callNode); const RetICFGNode* retNode = callNode->getRetICFGNode(); - icfg->appendSubNode(retNode, retNode); - icfg->addRepNode(retNode, retNode); - bbToNodes[bb].push_back(retNode); - simplifiedNodes.insert(retNode); + subNodes.insert(retNode); } else { // For ordinary instructions, we put multiple instructions in an ICFGNode + /// e.g. + /// entry: + /// %add = add i32 %a, %b ----> goto branch 1 + /// %sub = sub i32 %add, %c -----> goto branch 2 + /// call void @fun() ----> call and ret has been handled + /// %mul = mul i32 %sub, %d -----> goto branch 3 if (bbToNodes.find(bb) == bbToNodes.end()) { - icfg->appendSubNode(icfgNode, icfgNode); - icfg->addRepNode(icfgNode, icfgNode); + // branch 1, for the first node of basic block bbToNodes[bb] = {icfgNode}; - simplifiedNodes.insert(icfgNode); + subNodes.insert(icfgNode); } else { const ICFGNode* pNode = bbToNodes[bb].back(); if (!SVFUtil::isa(pNode)) { - icfg->appendSubNode(pNode, icfgNode); - icfg->addRepNode(icfgNode, pNode); + // branch 2, for the middle node of basic block + // do nothing if it is not ret node } else { - icfg->appendSubNode(icfgNode, icfgNode); - icfg->addRepNode(icfgNode, icfgNode); + // branch 3, for the node after ret node bbToNodes[bb].push_back(icfgNode); - simplifiedNodes.insert(icfgNode); + subNodes.insert(icfgNode); } } } } } - if (const FunEntryICFGNode* funEntryNode = - icfg->getFunEntryICFGNode(func)) + if (const FunEntryICFGNode* funEntryNode = icfg->getFunEntryICFGNode(func)) { if (const SVFBasicBlock* bb = funEntryNode->getBB()) { std::vector& nodes = bbToNodes[bb]; - icfg->appendSubNode(funEntryNode, funEntryNode); - icfg->addRepNode(funEntryNode, funEntryNode); nodes.insert(nodes.begin(), funEntryNode); - simplifiedNodes.insert(funEntryNode); + subNodes.insert(funEntryNode); } } if (const FunExitICFGNode* funExitNode = icfg->getFunExitICFGNode(func)) @@ -120,186 +114,58 @@ static void mergeAdjacentNodes(ICFG* icfg) if (const SVFBasicBlock* bb = funExitNode->getBB()) { std::vector& nodes = bbToNodes[bb]; - icfg->appendSubNode(funExitNode, funExitNode); - icfg->addRepNode(funExitNode, funExitNode); nodes.push_back(funExitNode); - simplifiedNodes.insert(funExitNode); + subNodes.insert(funExitNode); } } } - for (auto &it: *icfg) { - if (simplifiedNodes.find(it.second) == simplifiedNodes.end() && - !SVFUtil::isa(it.second)) { - rm_nodes.insert(const_cast(it.second)); - } - } - - /// reconnect the ICFGNodes, - /// 1. intraCFGEdges between different basicblocks, but in the safe function e.g. entry: - /// cond = icmp eq i32 %a, 0 ---------> srcblk - /// br i1 cond, label %bb1, label %bb2 ---------> srcblk_tail - /// bb1: - /// ... --------> dstblk - /// bb2: - /// ... --------> another dstblk - /// tmpEdge is the edge between srcblk and dstblk, may have condition var (cond is true or false) - for (const auto& node : *icfg) - { - for (const auto& succ : node.second->getOutEdges()) - { - if (succ->isIntraCFGEdge()) - { - const SVFFunction* node_fun = node.second->getFun(); - const SVFFunction* succ_fun = succ->getDstNode()->getFun(); - const SVFBasicBlock* node_bb = node.second->getBB(); - const SVFBasicBlock* succ_bb = succ->getDstNode()->getBB(); - if (node_fun == succ_fun) - { - if (node_bb != succ_bb) - { - ICFGNode* srcblk = const_cast( - bbToNodes[node_bb].back()); - ICFGNode* dstblk = const_cast( - bbToNodes[succ_bb].front()); - ICFGNode* srcblk_tail = const_cast( - icfg->getSubNodes(bbToNodes[node_bb].back()).back()); - ICFGEdge* tmpEdge = - icfg->getICFGEdge(srcblk_tail, dstblk, - ICFGEdge::ICFGEdgeK::IntraCF); - if (icfg->hasIntraICFGEdge(srcblk, dstblk, ICFGEdge::ICFGEdgeK::IntraCF)) { - continue; - } else { - if (tmpEdge) - { - IntraCFGEdge* intraEdge = - SVFUtil::dyn_cast(tmpEdge); - if (intraEdge->getCondition()) - icfg->addConditionalIntraEdge(srcblk, dstblk, intraEdge->getCondition(), intraEdge->getSuccessorCondValue()); - else - icfg->addIntraEdge(srcblk, dstblk); - } - else - { - icfg->addIntraEdge(srcblk, dstblk); - } + for (auto &it: subNodes) { + ICFGNode* head = const_cast(it); + if (head->getOutEdges().size() != 1) { + // if head has more than one out edges, we don't merge any following nodes. + continue; + } + else { + ICFGNode* next = (*head->getOutEdges().begin())->getDstNode(); + // merge the following nodes, until the next subnode + while (subNodes.find(next) == subNodes.end()) { + ICFGNode* rep_next = const_cast(icfg->getRepNode(next)); + assert(rep_next != head && "should not find a circle here"); + icfg->removeICFGEdge(*head->getOutEdges().begin()); + std::vector rm_edges; + // Step 1: merge the out edges of next to head + for (ICFGEdge* outEdge: next->getOutEdges()) { + rm_edges.push_back(outEdge); + ICFGNode* post = outEdge->getDstNode(); + if (outEdge->isIntraCFGEdge()) { + IntraCFGEdge* intraEdge = SVFUtil::dyn_cast(outEdge); + if (intraEdge->getCondition()) { + icfg->addConditionalIntraEdge(head, post, intraEdge->getCondition(), intraEdge->getSuccessorCondValue()); + } + else { + icfg->addIntraEdge(head, post); } } } - } - } - } + // Step 2: update the sub node map and rep node map + icfg->addRepNode(next, head); + icfg->addSubNode(next, head); + if (next->getOutEdges().size() == 1) { + // Step 3: remove the edges from next to its next, since next has been merged to head + // if only one out edge, we may continue to merge the next node if it is not a subnode + next = (*next->getOutEdges().begin())->getDstNode(); + for (ICFGEdge* edge: rm_edges) + icfg->removeICFGEdge(edge); - /// 2. intraCFGEdges in the same basicblock, but seperated by callInst - /// e.g. entry: - /// ..... --------> bbNode0 - /// call void @foo() ---------> callNode: bbNode1, retNode bbNode2 - /// ..... --------> bbNode3 - /// entry block has 4 bbNodes. the following for loop just links bbNodes in the same basic block. - for (const auto& bbNodes : bbToNodes) - { - for (u32_t i = 0; i < bbNodes.second.size() - 1; ++i) - { - ICFGNode* srcblk_tail = - const_cast(icfg->getSubNodes(bbNodes.second[i]).back()); - ICFGNode* srcblk = const_cast(bbNodes.second[i]); - ICFGNode* dstblk = const_cast(bbNodes.second[i + 1]); - if (!icfg->hasIntraICFGEdge(srcblk_tail, dstblk, - ICFGEdge::ICFGEdgeK::IntraCF)) - { - continue; - } - - if (icfg->hasIntraICFGEdge(srcblk, dstblk, - ICFGEdge::ICFGEdgeK::IntraCF)) - { - continue; - } - else - { - icfg->addIntraEdge(srcblk, dstblk); - } - } - } - - /// 3. CallCFGEdges and RetCFGEdges - /// CallEdge is the edge between CallNode and FunEntryNode. - /// RetEdge is the edge between FunExitNode and RetNode. - - for (const auto& bbNodes : bbToNodes) - { - for (u32_t i = 0; i < bbNodes.second.size(); ++i) - { - if (const CallICFGNode* callICFGNode = - SVFUtil::dyn_cast(bbNodes.second[i])) - { - for (const auto& icfgEdge : callICFGNode->getOutEdges()) - { - if (const CallCFGEdge* callEdge = - SVFUtil::dyn_cast(icfgEdge)) - { - ICFGNode* srcblk = - const_cast(bbNodes.second[i]); - ICFGNode* dstblk = - const_cast(callEdge->getDstNode()); - if (icfg->hasIntraICFGEdge(srcblk, dstblk, - ICFGEdge::ICFGEdgeK::CallCF)) - continue; - else - { - icfg->addCallEdge(srcblk, dstblk, callICFGNode->getCallSite()); - } - } } - } - else if (const RetICFGNode* retICFGNode = - SVFUtil::dyn_cast(bbNodes.second[i])) - { - for (const auto& icfgEdge : retICFGNode->getInEdges()) - { - if (const RetCFGEdge* retEdge = - SVFUtil::dyn_cast(icfgEdge)) - { - if (!retEdge->getSrcNode()->getFun()->hasReturn()) - continue; - ICFGNode* srcblk = - const_cast(retEdge->getSrcNode()); - ICFGNode* dstblk = - const_cast(bbNodes.second[i]); - if (icfg->hasIntraICFGEdge(srcblk, dstblk, - ICFGEdge::ICFGEdgeK::RetCF)) - continue; - else - { - icfg->addRetEdge(srcblk, dstblk, retICFGNode->getCallSite()); - } - } + else { + // if more than one out edges, we don't merge any following nodes. + for (ICFGEdge* edge: rm_edges) + icfg->removeICFGEdge(edge); + break; } } - else - { - } - } - } - for (auto& it : rm_nodes) - { - ICFGNode* node = it; - Set rm_outedges, rm_inedges; - for (ICFGEdge* edge : node->getOutEdges()) - { - rm_outedges.insert(edge); - } - for (ICFGEdge* edge : node->getInEdges()) - { - rm_inedges.insert(edge); - } - for (ICFGEdge* edge : rm_outedges) - { - icfg->removeICFGEdge(edge); - } - for (ICFGEdge* edge : rm_inedges) - { - icfg->removeICFGEdge(edge); } } } diff --git a/svf/include/Graphs/ICFG.h b/svf/include/Graphs/ICFG.h index 20b6071f7..9e2aa0570 100644 --- a/svf/include/Graphs/ICFG.h +++ b/svf/include/Graphs/ICFG.h @@ -188,6 +188,8 @@ class ICFG : public GenericICFGTy virtual inline void addICFGNode(ICFGNode* node) { addGNode(node->getId(),node); + _repNode[node] = node; + _subNodes[node].push_back(node); } public: @@ -216,24 +218,23 @@ class ICFG : public GenericICFGTy addICFGNode(globalBlockNode); } - - virtual std::vector getSubNodes(const ICFGNode* node) const { - return _subNodes.find(node) == _subNodes.end()? std::vector({node}): _subNodes.at(node); + const std::vector& getSubNodes(const ICFGNode* node) const { + return _subNodes.at(node); } - virtual const ICFGNode* getRepNode(const ICFGNode* node) const { - return _repNode.find(node) == _repNode.end()? node: _repNode.at(node); + const ICFGNode* getRepNode(const ICFGNode* node) const { + return _repNode.at(node); } - virtual void appendSubNode(const ICFGNode* key, const ICFGNode* value) { - if(_subNodes.find(key) == _subNodes.end()) { - _subNodes[key] = std::vector(); - } - _subNodes[key].push_back(value); + void addSubNode(const ICFGNode* rep, const ICFGNode* sub) { + std::vector& subNodes = _subNodes[sub]; + if(std::find(subNodes.begin(), subNodes.end(), rep) == subNodes.end()) { + subNodes.push_back(rep); + } } - virtual void addRepNode(const ICFGNode* key, const ICFGNode* value) { - _repNode[key] = value; + void addRepNode(const ICFGNode* rep, const ICFGNode* sub) { + _repNode[sub] = rep; } //@} From c9413d2309684e903d56ce8ec463e785e000b4a1 Mon Sep 17 00:00:00 2001 From: bjjwwang Date: Thu, 29 Feb 2024 17:17:31 +1100 Subject: [PATCH 19/22] refactor the algorithm --- svf/include/AE/Svfexe/ICFGSimplification.h | 4 ++++ svf/include/Graphs/ICFG.h | 22 +++++++++++++++------- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/svf/include/AE/Svfexe/ICFGSimplification.h b/svf/include/AE/Svfexe/ICFGSimplification.h index c048b3dc0..3f931f39d 100644 --- a/svf/include/AE/Svfexe/ICFGSimplification.h +++ b/svf/include/AE/Svfexe/ICFGSimplification.h @@ -61,9 +61,11 @@ static void mergeAdjacentNodes(ICFG* icfg) if (const CallICFGNode* callNode = SVFUtil::dyn_cast(icfgNode)) { + bbToNodes[bb].push_back(callNode); subNodes.insert(callNode); const RetICFGNode* retNode = callNode->getRetICFGNode(); + bbToNodes[bb].push_back(retNode); subNodes.insert(retNode); } else @@ -149,6 +151,7 @@ static void mergeAdjacentNodes(ICFG* icfg) } } // Step 2: update the sub node map and rep node map + icfg->update icfg->addRepNode(next, head); icfg->addSubNode(next, head); if (next->getOutEdges().size() == 1) { @@ -168,6 +171,7 @@ static void mergeAdjacentNodes(ICFG* icfg) } } } + icfg->dump("icfg_simp"); } }; } \ No newline at end of file diff --git a/svf/include/Graphs/ICFG.h b/svf/include/Graphs/ICFG.h index 9e2aa0570..8d2ff2d94 100644 --- a/svf/include/Graphs/ICFG.h +++ b/svf/include/Graphs/ICFG.h @@ -226,19 +226,27 @@ class ICFG : public GenericICFGTy return _repNode.at(node); } + + void updateSubRepNode(const ICFGNode* rep, const ICFGNode* sub) { + addSubNode(rep, sub); + addRepNode(rep, sub); + } + //@} + +private: + /// when ICFG is simplified, SubNode would merge repNode, then update the map void addSubNode(const ICFGNode* rep, const ICFGNode* sub) { - std::vector& subNodes = _subNodes[sub]; - if(std::find(subNodes.begin(), subNodes.end(), rep) == subNodes.end()) { - subNodes.push_back(rep); - } + std::vector& subNodes = _subNodes[sub]; + if(std::find(subNodes.begin(), subNodes.end(), rep) == subNodes.end()) { + subNodes.push_back(rep); + } } + /// when ICFG is simplified, some node would be removed, this map records the removed node to its rep node void addRepNode(const ICFGNode* rep, const ICFGNode* sub) { - _repNode[sub] = rep; + _repNode[rep] = sub; } - //@} -private: /// Add ICFG edge, only used by addIntraEdge, addCallEdge, addRetEdge etc. inline bool addICFGEdge(ICFGEdge* edge) { From 3b99c8f7115756bfd1e7949b059877f31f186388 Mon Sep 17 00:00:00 2001 From: bjjwwang Date: Thu, 29 Feb 2024 19:40:08 +1100 Subject: [PATCH 20/22] fix a coding err --- svf/include/AE/Svfexe/ICFGSimplification.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/svf/include/AE/Svfexe/ICFGSimplification.h b/svf/include/AE/Svfexe/ICFGSimplification.h index 3f931f39d..85865295e 100644 --- a/svf/include/AE/Svfexe/ICFGSimplification.h +++ b/svf/include/AE/Svfexe/ICFGSimplification.h @@ -151,9 +151,7 @@ static void mergeAdjacentNodes(ICFG* icfg) } } // Step 2: update the sub node map and rep node map - icfg->update - icfg->addRepNode(next, head); - icfg->addSubNode(next, head); + icfg->updateSubRepNode(next, head); if (next->getOutEdges().size() == 1) { // Step 3: remove the edges from next to its next, since next has been merged to head // if only one out edge, we may continue to merge the next node if it is not a subnode @@ -171,7 +169,6 @@ static void mergeAdjacentNodes(ICFG* icfg) } } } - icfg->dump("icfg_simp"); } }; } \ No newline at end of file From df4dd255b4572ddbab7f610c5e6c72ff9db2d20e Mon Sep 17 00:00:00 2001 From: bjjwwang Date: Sat, 2 Mar 2024 21:31:02 +1100 Subject: [PATCH 21/22] rename apis --- svf/include/AE/Svfexe/ICFGSimplification.h | 2 +- svf/include/Graphs/ICFG.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/svf/include/AE/Svfexe/ICFGSimplification.h b/svf/include/AE/Svfexe/ICFGSimplification.h index 85865295e..6e643cafc 100644 --- a/svf/include/AE/Svfexe/ICFGSimplification.h +++ b/svf/include/AE/Svfexe/ICFGSimplification.h @@ -151,7 +151,7 @@ static void mergeAdjacentNodes(ICFG* icfg) } } // Step 2: update the sub node map and rep node map - icfg->updateSubRepNode(next, head); + icfg->updateSubAndRep(next, head); if (next->getOutEdges().size() == 1) { // Step 3: remove the edges from next to its next, since next has been merged to head // if only one out edge, we may continue to merge the next node if it is not a subnode diff --git a/svf/include/Graphs/ICFG.h b/svf/include/Graphs/ICFG.h index 8d2ff2d94..caf2a6a6b 100644 --- a/svf/include/Graphs/ICFG.h +++ b/svf/include/Graphs/ICFG.h @@ -227,9 +227,9 @@ class ICFG : public GenericICFGTy } - void updateSubRepNode(const ICFGNode* rep, const ICFGNode* sub) { + void updateSubAndRep(const ICFGNode* rep, const ICFGNode* sub) { addSubNode(rep, sub); - addRepNode(rep, sub); + updateRepNode(rep, sub); } //@} @@ -243,7 +243,7 @@ class ICFG : public GenericICFGTy } /// when ICFG is simplified, some node would be removed, this map records the removed node to its rep node - void addRepNode(const ICFGNode* rep, const ICFGNode* sub) { + void updateRepNode(const ICFGNode* rep, const ICFGNode* sub) { _repNode[rep] = sub; } From abc4950e56a6f4cac5cd2740eee6bcfc7d794a7f Mon Sep 17 00:00:00 2001 From: bjjwwang Date: Sun, 3 Mar 2024 14:42:35 +1100 Subject: [PATCH 22/22] move impl to cpp --- svf/include/AE/Svfexe/ICFGSimplification.h | 130 +---------------- svf/include/Graphs/ICFG.h | 2 +- svf/lib/AE/Svfexe/ICFGSimplification.cpp | 162 +++++++++++++++++++++ 3 files changed, 164 insertions(+), 130 deletions(-) create mode 100644 svf/lib/AE/Svfexe/ICFGSimplification.cpp diff --git a/svf/include/AE/Svfexe/ICFGSimplification.h b/svf/include/AE/Svfexe/ICFGSimplification.h index 6e643cafc..d677f40f1 100644 --- a/svf/include/AE/Svfexe/ICFGSimplification.h +++ b/svf/include/AE/Svfexe/ICFGSimplification.h @@ -41,134 +41,6 @@ ICFGSimplification() = default; virtual ~ICFGSimplification() = default; -static void mergeAdjacentNodes(ICFG* icfg) -{ - Map> bbToNodes; - Set subNodes; - for (const auto& func : *PAG::getPAG()->getModule()) - { - for (const auto& bb : *func) - { - for (const auto& inst : *bb) - { - if (SVFUtil::isIntrinsicInst(inst)) - continue; - const ICFGNode* icfgNode = icfg->getICFGNode(inst); - // e.g. - // block: entry - // insts: call = i32 %fun(i32 %arg) - // We put the callnode in an icfgnode alone, and the retnode is similar. - if (const CallICFGNode* callNode = - SVFUtil::dyn_cast(icfgNode)) - { - bbToNodes[bb].push_back(callNode); - subNodes.insert(callNode); - - const RetICFGNode* retNode = callNode->getRetICFGNode(); - bbToNodes[bb].push_back(retNode); - subNodes.insert(retNode); - } - else - { - // For ordinary instructions, we put multiple instructions in an ICFGNode - /// e.g. - /// entry: - /// %add = add i32 %a, %b ----> goto branch 1 - /// %sub = sub i32 %add, %c -----> goto branch 2 - /// call void @fun() ----> call and ret has been handled - /// %mul = mul i32 %sub, %d -----> goto branch 3 - if (bbToNodes.find(bb) == bbToNodes.end()) - { - // branch 1, for the first node of basic block - bbToNodes[bb] = {icfgNode}; - subNodes.insert(icfgNode); - } - else - { - const ICFGNode* pNode = bbToNodes[bb].back(); - if (!SVFUtil::isa(pNode)) - { - // branch 2, for the middle node of basic block - // do nothing if it is not ret node - } - else - { - // branch 3, for the node after ret node - bbToNodes[bb].push_back(icfgNode); - subNodes.insert(icfgNode); - } - } - } - } - } - - if (const FunEntryICFGNode* funEntryNode = icfg->getFunEntryICFGNode(func)) - { - if (const SVFBasicBlock* bb = funEntryNode->getBB()) - { - std::vector& nodes = bbToNodes[bb]; - nodes.insert(nodes.begin(), funEntryNode); - subNodes.insert(funEntryNode); - } - } - if (const FunExitICFGNode* funExitNode = icfg->getFunExitICFGNode(func)) - { - if (const SVFBasicBlock* bb = funExitNode->getBB()) - { - std::vector& nodes = bbToNodes[bb]; - nodes.push_back(funExitNode); - subNodes.insert(funExitNode); - } - } - } - - for (auto &it: subNodes) { - ICFGNode* head = const_cast(it); - if (head->getOutEdges().size() != 1) { - // if head has more than one out edges, we don't merge any following nodes. - continue; - } - else { - ICFGNode* next = (*head->getOutEdges().begin())->getDstNode(); - // merge the following nodes, until the next subnode - while (subNodes.find(next) == subNodes.end()) { - ICFGNode* rep_next = const_cast(icfg->getRepNode(next)); - assert(rep_next != head && "should not find a circle here"); - icfg->removeICFGEdge(*head->getOutEdges().begin()); - std::vector rm_edges; - // Step 1: merge the out edges of next to head - for (ICFGEdge* outEdge: next->getOutEdges()) { - rm_edges.push_back(outEdge); - ICFGNode* post = outEdge->getDstNode(); - if (outEdge->isIntraCFGEdge()) { - IntraCFGEdge* intraEdge = SVFUtil::dyn_cast(outEdge); - if (intraEdge->getCondition()) { - icfg->addConditionalIntraEdge(head, post, intraEdge->getCondition(), intraEdge->getSuccessorCondValue()); - } - else { - icfg->addIntraEdge(head, post); - } - } - } - // Step 2: update the sub node map and rep node map - icfg->updateSubAndRep(next, head); - if (next->getOutEdges().size() == 1) { - // Step 3: remove the edges from next to its next, since next has been merged to head - // if only one out edge, we may continue to merge the next node if it is not a subnode - next = (*next->getOutEdges().begin())->getDstNode(); - for (ICFGEdge* edge: rm_edges) - icfg->removeICFGEdge(edge); - - } - else { - // if more than one out edges, we don't merge any following nodes. - for (ICFGEdge* edge: rm_edges) - icfg->removeICFGEdge(edge); - break; - } - } - } - } -} +static void mergeAdjacentNodes(ICFG* icfg); }; } \ No newline at end of file diff --git a/svf/include/Graphs/ICFG.h b/svf/include/Graphs/ICFG.h index caf2a6a6b..9a2111757 100644 --- a/svf/include/Graphs/ICFG.h +++ b/svf/include/Graphs/ICFG.h @@ -152,7 +152,7 @@ class ICFG : public GenericICFGTy } protected: - /// Add control-flow edges for top level pointers + /// Add intraprocedural and interprocedural control-flow edges. //@{ ICFGEdge* addIntraEdge(ICFGNode* srcNode, ICFGNode* dstNode); ICFGEdge* addConditionalIntraEdge(ICFGNode* srcNode, ICFGNode* dstNode, const SVFValue* condition, s32_t branchCondVal); diff --git a/svf/lib/AE/Svfexe/ICFGSimplification.cpp b/svf/lib/AE/Svfexe/ICFGSimplification.cpp new file mode 100644 index 000000000..47b5bbe12 --- /dev/null +++ b/svf/lib/AE/Svfexe/ICFGSimplification.cpp @@ -0,0 +1,162 @@ +//===- ICFGSimplification.h -- Simplify ICFG----------------------------------// +// +// SVF: Static Value-Flow Analysis +// +// Copyright (C) <2013-> +// + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. + +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +// +// The implementation is based on +// Xiao Cheng, Jiawei Wang and Yulei Sui. Precise Sparse Abstract Execution via Cross-Domain Interaction. +// 46th International Conference on Software Engineering. (ICSE24) +//===----------------------------------------------------------------------===// + + +// +// Created by Jiawei Wang on 2024/2/25. +// +#include "AE/Svfexe/ICFGSimplification.h" + +namespace SVF { +void ICFGSimplification::mergeAdjacentNodes(ICFG* icfg) +{ + Map> bbToNodes; + Set subNodes; + for (const auto& func : *PAG::getPAG()->getModule()) + { + for (const auto& bb : *func) + { + for (const auto& inst : *bb) + { + if (SVFUtil::isIntrinsicInst(inst)) + continue; + const ICFGNode* icfgNode = icfg->getICFGNode(inst); + // e.g. + // block: entry + // insts: call = i32 %fun(i32 %arg) + // We put the callnode in an icfgnode alone, and the retnode is similar. + if (const CallICFGNode* callNode = + SVFUtil::dyn_cast(icfgNode)) + { + bbToNodes[bb].push_back(callNode); + subNodes.insert(callNode); + + const RetICFGNode* retNode = callNode->getRetICFGNode(); + bbToNodes[bb].push_back(retNode); + subNodes.insert(retNode); + } + else + { + // For ordinary instructions, we put multiple instructions in an ICFGNode + /// e.g. + /// entry: + /// %add = add i32 %a, %b ----> goto branch 1 + /// %sub = sub i32 %add, %c -----> goto branch 2 + /// call void @fun() ----> call and ret has been handled + /// %mul = mul i32 %sub, %d -----> goto branch 3 + if (bbToNodes.find(bb) == bbToNodes.end()) + { + // branch 1, for the first node of basic block + bbToNodes[bb] = {icfgNode}; + subNodes.insert(icfgNode); + } + else + { + const ICFGNode* pNode = bbToNodes[bb].back(); + if (!SVFUtil::isa(pNode)) + { + // branch 2, for the middle node of basic block + // do nothing if it is not ret node + } + else + { + // branch 3, for the node after ret node + bbToNodes[bb].push_back(icfgNode); + subNodes.insert(icfgNode); + } + } + } + } + } + + if (const FunEntryICFGNode* funEntryNode = icfg->getFunEntryICFGNode(func)) + { + if (const SVFBasicBlock* bb = funEntryNode->getBB()) + { + std::vector& nodes = bbToNodes[bb]; + nodes.insert(nodes.begin(), funEntryNode); + subNodes.insert(funEntryNode); + } + } + if (const FunExitICFGNode* funExitNode = icfg->getFunExitICFGNode(func)) + { + if (const SVFBasicBlock* bb = funExitNode->getBB()) + { + std::vector& nodes = bbToNodes[bb]; + nodes.push_back(funExitNode); + subNodes.insert(funExitNode); + } + } + } + + for (auto &it: subNodes) { + ICFGNode* head = const_cast(it); + if (head->getOutEdges().size() != 1) { + // if head has more than one out edges, we don't merge any following nodes. + continue; + } + else { + ICFGNode* next = (*head->getOutEdges().begin())->getDstNode(); + // merge the following nodes, until the next subnode + while (subNodes.find(next) == subNodes.end()) { + ICFGNode* rep_next = const_cast(icfg->getRepNode(next)); + assert(rep_next != head && "should not find a circle here"); + icfg->removeICFGEdge(*head->getOutEdges().begin()); + std::vector rm_edges; + // Step 1: merge the out edges of next to head + for (ICFGEdge* outEdge: next->getOutEdges()) { + rm_edges.push_back(outEdge); + ICFGNode* post = outEdge->getDstNode(); + if (outEdge->isIntraCFGEdge()) { + IntraCFGEdge* intraEdge = SVFUtil::dyn_cast(outEdge); + if (intraEdge->getCondition()) { + icfg->addConditionalIntraEdge(head, post, intraEdge->getCondition(), intraEdge->getSuccessorCondValue()); + } + else { + icfg->addIntraEdge(head, post); + } + } + } + // Step 2: update the sub node map and rep node map + icfg->updateSubAndRep(next, head); + if (next->getOutEdges().size() == 1) { + // Step 3: remove the edges from next to its next, since next has been merged to head + // if only one out edge, we may continue to merge the next node if it is not a subnode + next = (*next->getOutEdges().begin())->getDstNode(); + for (ICFGEdge* edge: rm_edges) + icfg->removeICFGEdge(edge); + + } + else { + // if more than one out edges, we don't merge any following nodes. + for (ICFGEdge* edge: rm_edges) + icfg->removeICFGEdge(edge); + break; + } + } + } + } +} +} \ No newline at end of file