WALA---Java程序静态切片技术

上一次,我们讲述了如何使用wala对类进行最简单的分析,这次将使用wala工具,进行静态切片分析。

如果对切片不是很熟悉,可以直接搜索 程序切片,有很多关于切片技术的讲解,这里不在讲述。

步入主题:

首先,在上一次ClassHierarchy cha的基础上,需要构建入口点,分析选项,反射机制,如下所示:

        Iterable<Entrypoint> entrypoints =Util.makeMainEntrypoints(scope, cha);
        AnalysisOptions options = new AnalysisOptions(scope, entrypoints);
        options.setReflectionOptions(ReflectionOptions.NONE);  

随后,我们需要构建call graph:

    // 这里,Util类下有很多builder函数,具体含义我个人也不是很清楚,希望懂的大神可以分享,万分感谢。

       CallGraphBuilder<InstanceKey> builder = Util.makeVanillaZeroOneCFABuilder(options, new AnalysisCacheImpl(), cha, scope);

       CallGraph cg = builder.makeCallGraph(options, null);

       可以使用cg图,加数据流控制流选项直接进行切片,但是这里不建议这样子使用,因为切片是基于sdg图进行的,所以这里先构建sdg图:

        // Build sdg
        final PointerAnalysis<InstanceKey> pa = builder.getPointerAnalysis();  
        SDG<?> sdg = new SDG<>(cg, pa, modRef, DataDependenceOptions.REFLECTION, ControlDependenceOptions.NO_EXCEPTIONAL_EDGES, null);

函数重点modRef,需要在加private ModRef<InstanceKey> modRef = ModRef.make(); 其余的参数可以通过eclipse中查看,可以对照wala的源代码进行查看。

构建完sdg图,就可以进行切片分析,wala工具有直接的切片入口,但是调用之前,我们需要知道seed是什么(补充一点,目前我个人所掌握的智能通过函数调用这样的方式得到seed,如果有哪位大神可以使用其他类型的seed,请留言告知,这里万分感谢!!!)。

   第一步,创建一个collection,用于存储结果,Collection<Statement> collection = null;

第二步,我们需要知道,seed在哪个函数中,所以,我们要先在cg图里找到哪个节点是对应的函数,

//cg图,函数名,函数所在的类

public CGNode findMethod(CallGraph cg, String Name, String methodCLass) {
        if(Name.equals(null) && methodCLass.equals(null))
            return null;

     //构建 atom(wala中),用来比较CGNode的名字和类

       Atom name = Atom.findOrCreateUnicodeAtom(Name);

     //迭代cg图

        for (Iterator<? extends CGNode> it = cg.iterator(); it.hasNext();) {
            CGNode n = it.next();

            // 函数名和类名比较

            if (n.getMethod().getName().equals(name) &&
                    n.getMethod().getDeclaringClass().getName().toString().equals(methodCLass)) {
                return n;
            }
        }
        Assertions.UNREACHABLE("Failed to find method " + name);
        return null;
    }

第三步,在CGNode中找到seed

//  n是第二步的返回值,methodName是seed的函数名

public Statement findCallTo(CGNode n, String methodName) {

       // 函数n的ir,中间表示(和llvm的ir很相似)。

        IR ir = n.getIR();
        //System.out.println(ir.toString());

       //迭代ir中每一条指令,寻找seed

        for (Iterator<SSAInstruction> it = ir.iterateAllInstructions(); it.hasNext();) {
            SSAInstruction s = it.next();

            // 当前指令是调用指令,比较函数名,是否是seed;

            if (s instanceof SSAInvokeInstruction) {
                SSAInvokeInstruction call = (SSAInvokeInstruction) s;
                if (call.getCallSite().getDeclaredTarget().getName().toString().equals(methodName)) {
                    IntSet indices = ir.getCallInstructionIndices(call.getCallSite());
                    Assertions.productionAssertion(indices.size() == 1,
                            "expected 1 but got " + indices.size());
                    return new NormalStatement(n, indices.intIterator().next());
                }
            }
        }
        Assertions.UNREACHABLE("Failed to find call to " + methodName + " in " + n);
        return null;
    }

第四步,切片分析;

CGNode n = findMethod(cg, callname, callmethodClass);

Statement statement = findCallTo(n, methodName);

//自动导入包即可,slicer还有很多方法,如反向切片,上下文敏感等

collection = Slicer.computeForwardSlice(sdg, statement);

//如果要使用瘦切片

ThinSlicer ts = new ThinSlicer(cg,pa);
        Collection<Statement> slice = ts.computeBackwardThinSlice ( statement );
最后,只需要将得到的collection遍历打印就可以看到结果了


public static void dumpSlice(Collection<Statement> slice) {
      for (Statement s : slice) {
        System.err.println(s);
      }
    }

本次wala切片使用的心得就写到这里,我这里也是参考了wala官网的例子。

http://wala.sourceforge.net/wiki/index.php/UserGuide:Slicer


以上都是个人使用经验且全部可以运行,如有错误,希望各位大神批评改正,也很期待私信交流。






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值