Skip to content

A simple driver example of SVF

Yulei Sui edited this page Sep 26, 2021 · 14 revisions

The simple driver program can be found at SVF-tools/SVF-example. After building SVF, its corresponding executable is svf-ex under the bin folder.

We discuss the driver program in detail as follows:

/*!
 * A driver program to obtain PointerAnalysis, PAG, CallGraph, ICFG and SVFG.
 */

int main(int argc, char ** argv) {

    int arg_num = 0;
    char **arg_value = new char*[argc];
    std::vector<std::string> moduleNameVec;
    SVFUtil::processArguments(argc, argv, arg_num, arg_value, moduleNameVec);
    cl::ParseCommandLineOptions(arg_num, arg_value,
                                "Whole Program Points-to Analysis\n");

    SVFModule* svfModule = LLVMModuleSet::getLLVMModuleSet()->buildSVFModule(moduleNameVec);
    svfModule->buildSymbolTableInfo();
    
    /// Build Program Assignment Graph (PAG)
    PAGBuilder builder;
    PAG *pag = builder.build(svfModule);
    pag->dump("pag");

    /// Create Andersen's pointer analysis
    Andersen *ander = AndersenWaveDiff::createAndersenWaveDiff(pag);

    /// Program Assignment Graph (PAG)
    PAG* pag = ander->getPAG();

    /// Call Graph
    PTACallGraph callgraph = ander->getPTACallGraph();

    /// ICFG
    ICFG* icfg = pag->getICFG();

    /// Sparse value-flow graph (SVFG)
    SVFGBuilder svfBuilder;
    SVFG* svfg = svfBuilder.buildFullSVFG(ander);

    /// Collect uses of an LLVM Value
    /// collectUsesOnVFG(svfg, value);

    return 0;
}

/*!
 * An example to query alias results of two LLVM values
 */
AliasResult aliasQuery(PointerAnalysis* pta, Value* v1, Value* v2){
	return pta->alias(v1,v2);
}
/*!
 * An example to print points-to set of an LLVM value
 */
std::string printPts(PointerAnalysis* pta, Value* val){

    std::string str;
    raw_string_ostream rawstr(str);

    NodeID pNodeId = pta->getPAG()->getValueNode(val);
    NodeBS& pts = pta->getPts(pNodeId);
    for (NodeBS::iterator ii = pts.begin(), ie = pts.end();
            ii != ie; ii++) {
        rawstr << " " << *ii << " ";
        PAGNode* targetObj = pta->getPAG()->getPAGNode(*ii);
        if(targetObj->hasValue()){
            rawstr << "(" <<*targetObj->getValue() << ")\t ";
        }
    }

    return rawstr.str();

}
/*!
 * An example to query/collect all the uses of a definition of a value along value-flow graph (VFG)
 */
void collectUsesOnVFG(const SVFG* vfg, Value* val){
	PAG* pag = PAG::getPAG();

    PAGNode* pNode = pag->getPAGNode(pag->getValueNode(val));
    const VFGNode* vNode = vfg->getDefSVFGNode(pNode);
    FIFOWorkList<const VFGNode*> worklist;
    std::set<const VFGNode*> visited;
    worklist.push(vNode);

    /// Traverse along VFG
    while(!worklist.empty()){
    	const VFGNode* vNode = worklist.pop();
    	for(VFGNode::const_iterator it = vNode->OutEdgeBegin(), eit = vNode->OutEdgeEnd(); it!=eit; ++it) {
            if(visited.find(vNode)==visited.end()){
            	visited.insert(vNode);
            	worklist.push(vNode);
            }
    	}
    }

    /// Collect all LLVM Values
    for(std::set<const VFGNode*>::const_iterator it = visited.begin(), eit = visited.end(); it!=eit; ++it){
    	const VFGNode* node = *it;
    	/// can only query VFGNode involving top-level pointers (starting with % or @ in LLVM IR)
    	/// PAGNode* pNode = vfg->getLHSTopLevPtr(node);
    	/// Value* val = pNode->getValue();
    }
}