Skip to content

Commit

Permalink
Merge pull request #1253 from bjjwwang/1107
Browse files Browse the repository at this point in the history
fix CFBBGraph for recursive funcs
  • Loading branch information
yuleisui authored Nov 22, 2023
2 parents 90b0863 + e351998 commit e8ce5b8
Showing 1 changed file with 79 additions and 34 deletions.
113 changes: 79 additions & 34 deletions svf/lib/Util/CFBasicBlockGBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,29 +31,37 @@
namespace SVF
{

/**
* Initialize Control Flow Basic Block Graph (CFBasicBlockG) nodes based on the provided Interprocedural Control Flow Graph (ICFG).
*
* @param icfg The Interprocedural Control Flow Graph (ICFG) to initialize from.
* @param bbToNodes A map that associates each SVFBasicBlock with a vector of CFBasicBlockNode objects.
*/
void CFBasicBlockGBuilder::initCFBasicBlockGNodes(ICFG *icfg,
Map<const SVFBasicBlock *, std::vector<CFBasicBlockNode *>> &bbToNodes)
Map<const SVFBasicBlock *, std::vector<CFBasicBlockNode *>> &bbToNodes)
{
for (const auto &node: *icfg)
for (const auto &node : *icfg)
{
CFBasicBlockNode *pNode;
if (const SVFBasicBlock *bb = node.second->getBB())
{
if (const CallICFGNode *callNode = SVFUtil::dyn_cast<CallICFGNode>(node.second))
{
// Create a new CFBasicBlockNode for the CallICFGNode
pNode = new CFBasicBlockNode({callNode});
bbToNodes[bb].push_back(pNode);
_CFBasicBlockG->addCFBBNode(pNode);

// Create a new CFBasicBlockNode for the corresponding RetICFGNode
auto *retNode = new CFBasicBlockNode({callNode->getRetICFGNode()});
bbToNodes[bb].push_back(retNode);
_CFBasicBlockG->addCFBBNode(retNode);

}
else if (!SVFUtil::isa<RetICFGNode>(node.second))
{
if (bbToNodes.find(bb) == bbToNodes.end())
{
// Create a new CFBasicBlockNode for the non-CallICFGNode
pNode = new CFBasicBlockNode({node.second});
bbToNodes[node.second->getBB()] = {pNode};
_CFBasicBlockG->addCFBBNode(pNode);
Expand All @@ -63,10 +71,12 @@ void CFBasicBlockGBuilder::initCFBasicBlockGNodes(ICFG *icfg,
pNode = bbToNodes[node.second->getBB()].back();
if (!SVFUtil::isa<RetICFGNode>(pNode->getICFGNodes()[0]))
{
// Add the non-CallICFGNode to the existing CFBasicBlockNode
pNode->addNode(node.second);
}
else
{
// Create a new CFBasicBlockNode for the non-CallICFGNode
pNode = new CFBasicBlockNode({node.second});
bbToNodes[node.second->getBB()].push_back(pNode);
_CFBasicBlockG->addCFBBNode(pNode);
Expand All @@ -77,107 +87,142 @@ void CFBasicBlockGBuilder::initCFBasicBlockGNodes(ICFG *icfg,
}
}


/**
* Add inter-BasicBlock edges to the Control Flow Basic Block Graph (CFBasicBlockG) based on the provided Interprocedural Control Flow Graph (ICFG).
*
* @param icfg The Interprocedural Control Flow Graph (ICFG) to extract edges from.
* @param bbToNodes A map that associates each SVFBasicBlock with a vector of CFBasicBlockNode objects.
*/
void CFBasicBlockGBuilder::addInterBBEdge(ICFG *icfg,
Map<const SVFBasicBlock *, std::vector<CFBasicBlockNode *>> &bbToNodes)
Map<const SVFBasicBlock *, std::vector<CFBasicBlockNode *>> &bbToNodes)
{
// connect inter-BB BBNodes
for (const auto &node: *icfg)
// Connect inter-BB BBNodes
for (const auto &node : *icfg)
{
for (const auto &succ: node.second->getOutEdges())
for (const auto &succ : node.second->getOutEdges())
{
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)
// Check if it's an intraCFGEdge in case of recursive functions
// if recursive functions, node_fun == succ_fun but they are different call context
// edges related to recursive functions would be added in addInterProceduralEdge()
if (succ->isIntraCFGEdge())
{
if (node_bb != succ_bb)
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)
{
CFBasicBlockEdge *pEdge = new CFBasicBlockEdge(bbToNodes[node_bb].back(),
if (node_bb != succ_bb)
{
// Create a new CFBasicBlockEdge connecting the last node of the source BB
// and the first node of the destination BB
CFBasicBlockEdge *pEdge = new CFBasicBlockEdge(
bbToNodes[node_bb].back(),
bbToNodes[succ_bb].front(), succ);
_CFBasicBlockG->addCFBBEdge(pEdge);
_CFBasicBlockG->addCFBBEdge(pEdge);
}
}
}
}
}
}

/**
* Add intra-BasicBlock edges to the Control Flow Basic Block Graph (CFBasicBlockG) based on the provided Interprocedural Control Flow Graph (ICFG).
*
* @param icfg The Interprocedural Control Flow Graph (ICFG) to extract edges from.
* @param bbToNodes A map that associates each SVFBasicBlock with a vector of CFBasicBlockNode objects.
*/
void CFBasicBlockGBuilder::addIntraBBEdge(ICFG *icfg,
Map<const SVFBasicBlock *, std::vector<CFBasicBlockNode *>> &bbToNodes)
Map<const SVFBasicBlock *, std::vector<CFBasicBlockNode *>> &bbToNodes)
{
// connect intra-BB BBNodes
for (const auto &bbNodes: bbToNodes)
// Connect intra-BB BBNodes
for (const auto &bbNodes : bbToNodes)
{
for (u32_t i = 0; i < bbNodes.second.size() - 1; ++i)
{
// Check if an intraCFGEdge exists between the last node of the source BB and the first node of the destination BB
if (ICFGEdge *icfgEdge = icfg->getICFGEdge(
const_cast<ICFGNode *>(bbNodes.second[i]->getICFGNodes().back()),
const_cast<ICFGNode *>(bbNodes.second[i + 1]->getICFGNodes().front()),
ICFGEdge::IntraCF))
const_cast<ICFGNode *>(bbNodes.second[i]->getICFGNodes().back()),
const_cast<ICFGNode *>(bbNodes.second[i + 1]->getICFGNodes().front()),
ICFGEdge::IntraCF))
{
CFBasicBlockEdge *pEdge = new CFBasicBlockEdge(bbNodes.second[i], bbNodes.second[i + 1], icfgEdge);
_CFBasicBlockG->addCFBBEdge(pEdge);
}
else
{
// no intra-procedural edge, maybe ext api
// No intra-procedural edge found, possibly an external API call
}
}
}
}

/**
* Add inter-procedural edges between CFBasicBlockNodes based on the provided Interprocedural Control Flow Graph (ICFG).
*
* @param icfg The Interprocedural Control Flow Graph (ICFG) to extract edges from.
* @param bbToNodes A map that associates each SVFBasicBlock with a vector of CFBasicBlockNode objects.
*/
void CFBasicBlockGBuilder::addInterProceduralEdge(ICFG *icfg,
Map<const SVFBasicBlock *, std::vector<CFBasicBlockNode *>> &bbToNodes)
Map<const SVFBasicBlock *, std::vector<CFBasicBlockNode *>> &bbToNodes)
{
// connect inter-procedural BBNodes
for (const auto &bbNodes: bbToNodes)
// Connect inter-procedural BBNodes
for (const auto &bbNodes : bbToNodes)
{
for (u32_t i = 0; i < bbNodes.second.size(); ++i)
{
if (const CallICFGNode *callICFGNode = SVFUtil::dyn_cast<CallICFGNode>(
bbNodes.second[i]->getICFGNodes().front()))
{
for (const auto &icfgEdge: callICFGNode->getOutEdges())
for (const auto &icfgEdge : callICFGNode->getOutEdges())
{
if (const CallCFGEdge *callEdge = SVFUtil::dyn_cast<CallCFGEdge>(icfgEdge))
{
CFBasicBlockEdge *pEdge = new CFBasicBlockEdge(bbNodes.second[i],
bbToNodes[callEdge->getDstNode()->getBB()].front(),
callEdge);
bbToNodes[callEdge->getDstNode()->getBB()].front(),
callEdge);
_CFBasicBlockG->addCFBBEdge(pEdge);
}
}
}
else if (const RetICFGNode *retICFGNode = SVFUtil::dyn_cast<RetICFGNode>(
bbNodes.second[i]->getICFGNodes().front()))
{
for (const auto &icfgEdge: retICFGNode->getInEdges())
for (const auto &icfgEdge : retICFGNode->getInEdges())
{
if (const RetCFGEdge *retEdge = SVFUtil::dyn_cast<RetCFGEdge>(icfgEdge))
{
CFBasicBlockEdge *pEdge = new CFBasicBlockEdge(bbToNodes[retEdge->getSrcNode()->getBB()].back(),
bbNodes.second[i],
retEdge);
bbNodes.second[i],
retEdge);
_CFBasicBlockG->addCFBBEdge(pEdge);
}
}
}
else
{
// other nodes are intra-procedural
// Other nodes are intra-procedural
}
}
}
}

void CFBasicBlockGBuilder::build(ICFG* icfg)
/**
* Build the Control Flow Basic Block Graph (CFBasicBlockG) based on the provided Interprocedural Control Flow Graph (ICFG).
*
* @param icfg The Interprocedural Control Flow Graph (ICFG) to extract control flow information from.
*/
void CFBasicBlockGBuilder::build(ICFG *icfg)
{
_CFBasicBlockG = new CFBasicBlockGraph();
Map<const SVFBasicBlock*, std::vector<CFBasicBlockNode*>> bbToNodes;
Map<const SVFBasicBlock *, std::vector<CFBasicBlockNode *>> bbToNodes;

initCFBasicBlockGNodes(icfg, bbToNodes);
addInterBBEdge(icfg, bbToNodes);
addIntraBBEdge(icfg, bbToNodes);
addInterProceduralEdge(icfg, bbToNodes);
}

}

0 comments on commit e8ce5b8

Please sign in to comment.