尝试通过WALA检测源代码时出现异常:java.lang.ClassFormatError:StackMapTable格式错误:属性大小错误

时间:2017-02-02 14:08:42

标签: java eclipse-plugin instrumentation soot

我有一个像这样的简单程序:

package tests;

import java.util.Scanner;

public class TestSum {

    public static void main(String[] args) {
        int sum = 0;
        System.out.print("Please enter starting i: ");
        int i = new Scanner(System.in).nextInt();
        while ( i < 11 ) {
            sum = sum + i;
            i = i + 1;
        }
        System.out.println("sum = " + sum);
        System.out.println("Ending i = " + i);
    }
}

我将它构建到一个jar文件中,我想使用WALA添加更多的检测源代码来计算循环执行次数,以便进行动态分析。

这就是我使用Wala所做的事情,大部分内容都来自这个例子Wala Bench Example

import com.ibm.wala.shrikeBT.*;
import com.ibm.wala.shrikeBT.analysis.Verifier;
import com.ibm.wala.shrikeBT.shrikeCT.CTDecoder;
import com.ibm.wala.shrikeBT.shrikeCT.ClassInstrumenter;
import com.ibm.wala.shrikeBT.shrikeCT.OfflineInstrumenter;
import com.ibm.wala.shrikeCT.ClassWriter;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.PrintStream;
import java.io.Writer;

/**
 * Created by quocnghi on 2/2/17.
 */
public class InstrumentedTest {
    private final static boolean disasm = true;

    private final static boolean verify = true;

    private static OfflineInstrumenter instrumenter = new OfflineInstrumenter(true);

    public static void main(String[] args) throws Exception {
        for (int i = 0; i < 1; i++) {

            Writer w = new BufferedWriter(new FileWriter("report", false));

            args = instrumenter.parseStandardArgs(args);

            instrumenter.setPassUnmodifiedClasses(true);
            instrumenter.beginTraversal();
            ClassInstrumenter ci;
            while ((ci = instrumenter.nextClass()) != null) {
                doClass(ci, w);
            }
            instrumenter.close();
        }
    }

    static final String fieldName = "_Bench_enable_trace";

    // Keep these commonly used instructions around
    static final Instruction getSysOut = Util.makeGet(System.class, "out");

    static final Instruction callPrintln = Util.makeInvoke(PrintStream.class, "println", new Class[]{String.class});

    private static void doClass(final ClassInstrumenter ci, Writer w) throws Exception {
        final String className = ci.getReader().getName();
        System.out.println("Class name : " + className);
        w.write("Class: " + className + "\n");
        w.flush();

        for (int m = 0; m < ci.getReader().getMethodCount(); m++) {
            MethodData d = ci.visitMethod(m);
            System.out.println(d.getName());
            // d could be null, e.g., if the method is abstract or native
            if (d != null) {
                w.write("Instrumenting " + ci.getReader().getMethodName(m) + " " + ci.getReader().getMethodType(m) + ":\n");
                w.flush();

                if (disasm) {
                    w.write("Initial ShrikeBT code:\n");
                    (new Disassembler(d)).disassembleTo(w);
                    w.flush();
                }

                if (verify) {
                    Verifier v = new Verifier(d);
                    v.verify();
                }

                MethodEditor methodEditor = new MethodEditor(d);
                methodEditor.beginPass();

                final int noTraceLabel = methodEditor.allocateLabel();

                IInstruction[] instr = methodEditor.getInstructions();
                final String msg0 = "Loop called at " + Util.makeClass("L" + ci.getReader().getName() + ";") + "."
                        + ci.getReader().getMethodName(m);
                int i = 0;

                for (IInstruction in : instr) {
                    if (in instanceof ConditionalBranchInstruction) {

                        int b = i;
                        methodEditor.insertBefore(i, new MethodEditor.Patch() {
                            @Override
                            public void emitTo(MethodEditor.Output w) {
                                w.emit(getSysOut);
                                w.emit(ConstantInstruction.makeString(msg0));
                                w.emit(callPrintln);
                                w.emitLabel(noTraceLabel);
                            }
                        });
                    }

                    i++;
                    System.out.println(in.toString());
                }
                methodEditor.applyPatches();
                if (disasm) {
                    w.write("Final ShrikeBT code:\n");
                    (new Disassembler(d)).disassembleTo(w);
                    w.flush();
                }
            }
        }
        ClassWriter cw = ci.emitClass();
        instrumenter.outputModifiedClass(ci, cw);
    }
}

我希望在添加更多检测代码之后,程序应该变成这样,在循环中添加一行System.out.println:

包测试;

import java.util.Scanner;

public class TestSum {

    public static void main(String[] args) {
        int sum = 0;
        System.out.print("Please enter starting i: ");
        int i = new Scanner(System.in).nextInt();
        while ( i < 11 ) {
            sum = sum + i;
            i = i + 1;
            System.out.println("One count for this loop");
        }
        System.out.println("sum = " + sum);
        System.out.println("Ending i = " + i);
    }
}

但我收到了这个错误:

java.lang.ClassFormatError: StackMapTable format error: wrong attribute size

1 个答案:

答案 0 :(得分:0)

WALA does have StackMapTable support,但也许有些东西被打破了。我建议filing an issue