Example usage for org.objectweb.asm.tree InsnList insertBefore

List of usage examples for org.objectweb.asm.tree InsnList insertBefore

Introduction

In this page you can find the example usage for org.objectweb.asm.tree InsnList insertBefore.

Prototype

public void insertBefore(final AbstractInsnNode nextInsn, final InsnList insnList) 

Source Link

Document

Inserts the given instructions before the specified instruction.

Usage

From source file:com.lodgon.parboiled.transform.GroupClassGenerator.java

License:Apache License

protected void insertSetContextCalls(InstructionGroup group, int localVarIx) {
    InsnList instructions = group.getInstructions();
    for (InstructionGraphNode node : group.getNodes()) {
        if (node.isCallOnContextAware()) {
            AbstractInsnNode insn = node.getInstruction();

            if (node.getPredecessors().size() > 1) {
                // store the target of the call in a new local variable
                AbstractInsnNode loadTarget = node.getPredecessors().get(0).getInstruction();
                instructions.insert(loadTarget, new VarInsnNode(ASTORE, ++localVarIx));
                instructions.insert(loadTarget, new InsnNode(DUP)); // the DUP is inserted BEFORE the ASTORE

                // immediately before the call get the target from the local var and set the context on it
                instructions.insertBefore(insn, new VarInsnNode(ALOAD, localVarIx));
            } else {
                // if we have only one predecessor the call does not take any parameters and we can
                // skip the storing and loading of the invocation target
                instructions.insertBefore(insn, new InsnNode(DUP));
            }// w ww. j a  v a 2s.c  om
            instructions.insertBefore(insn, new VarInsnNode(ALOAD, 1));
            instructions.insertBefore(insn, new MethodInsnNode(INVOKEINTERFACE,
                    Types.CONTEXT_AWARE.getInternalName(), "setContext", "(" + Types.CONTEXT_DESC + ")V"));
        }
    }
}

From source file:com.lodgon.parboiled.transform.LabellingGenerator.java

License:Apache License

public void process(ParserClassNode classNode, RuleMethod method) throws Exception {
    checkArgNotNull(classNode, "classNode");
    checkArgNotNull(method, "method");
    checkState(!method.isSuperMethod()); // super methods have flag moved to the overriding method

    InsnList instructions = method.instructions;

    AbstractInsnNode ret = instructions.getLast();
    while (ret.getOpcode() != ARETURN) {
        ret = ret.getPrevious();/*from w  ww  .  j  a  v  a2 s. c o m*/
    }

    LabelNode isNullLabel = new LabelNode();
    // stack: <rule>
    instructions.insertBefore(ret, new InsnNode(DUP));
    // stack: <rule> :: <rule>
    instructions.insertBefore(ret, new JumpInsnNode(IFNULL, isNullLabel));
    // stack: <rule>
    instructions.insertBefore(ret, new LdcInsnNode(getLabelText(method)));
    // stack: <rule> :: <labelText>
    instructions.insertBefore(ret, new MethodInsnNode(INVOKEINTERFACE, Types.RULE.getInternalName(), "label",
            "(Ljava/lang/String;)" + Types.RULE_DESC));
    // stack: <rule>
    instructions.insertBefore(ret, isNullLabel);
    // stack: <rule>
}

From source file:com.lodgon.parboiled.transform.VarFramingGenerator.java

License:Apache License

public void process(ParserClassNode classNode, RuleMethod method) throws Exception {
    checkArgNotNull(classNode, "classNode");
    checkArgNotNull(method, "method");
    InsnList instructions = method.instructions;

    AbstractInsnNode ret = instructions.getLast();
    while (ret.getOpcode() != ARETURN) {
        ret = ret.getPrevious();/*from w ww  .  j  a v a  2s.c o m*/
    }

    // stack: <Matcher>
    instructions.insertBefore(ret, new TypeInsnNode(NEW, VAR_FRAMING_MATCHER.getInternalName()));
    // stack: <Matcher> :: <VarFramingMatcher>
    instructions.insertBefore(ret, new InsnNode(DUP_X1));
    // stack: <VarFramingMatcher> :: <Matcher> :: <VarFramingMatcher>
    instructions.insertBefore(ret, new InsnNode(SWAP));
    // stack: <VarFramingMatcher> :: <VarFramingMatcher> :: <Matcher>
    createVarFieldArray(method, instructions, ret);
    // stack: <VarFramingMatcher> :: <VarFramingMatcher> :: <Matcher> :: <VarFieldArray>
    instructions.insertBefore(ret, new MethodInsnNode(INVOKESPECIAL, VAR_FRAMING_MATCHER.getInternalName(),
            "<init>", '(' + RULE_DESC + '[' + VAR_DESC + ")V"));
    // stack: <VarFramingMatcher>

    method.setBodyRewritten();
}

From source file:com.lodgon.parboiled.transform.VarFramingGenerator.java

License:Apache License

private void createVarFieldArray(RuleMethod method, InsnList instructions, AbstractInsnNode ret) {
    int count = method.getLocalVarVariables().size();

    // stack://  w  w w  .  jav a  2  s.c o  m
    instructions.insertBefore(ret, new IntInsnNode(BIPUSH, count));
    // stack: <length>
    instructions.insertBefore(ret, new TypeInsnNode(ANEWARRAY, VAR.getInternalName()));
    // stack: <array>
    for (int i = 0; i < count; i++) {
        LocalVariableNode var = method.getLocalVarVariables().get(i);
        // stack: <array>
        instructions.insertBefore(ret, new InsnNode(DUP));
        // stack: <array> :: <array>
        instructions.insertBefore(ret, new IntInsnNode(BIPUSH, i));
        // stack: <array> :: <array> :: <index>
        instructions.insertBefore(ret, new VarInsnNode(ALOAD, var.index));
        // stack: <array> :: <array> :: <index> :: <var>
        instructions.insertBefore(ret, new InsnNode(DUP));
        // stack: <array> :: <array> :: <index> :: <var> :: <var>
        instructions.insertBefore(ret, new LdcInsnNode(method.name + ':' + var.name));
        // stack: <array> :: <array> :: <index> :: <var> :: <var> :: <varName>
        instructions.insertBefore(ret,
                new MethodInsnNode(INVOKEVIRTUAL, VAR.getInternalName(), "setName", "(Ljava/lang/String;)V"));
        // stack: <array> :: <array> :: <index> :: <var>
        instructions.insertBefore(ret, new InsnNode(AASTORE));
        // stack: <array>
    }
    // stack: <array>
}

From source file:com.sun.tdk.jcov.instrument.BranchCodeMethodAdapter.java

License:Open Source License

private void insertInstrumentation() {
    MethodNode methodNode = (MethodNode) mv;
    InsnList instructions = methodNode.instructions;

    for (Map.Entry<AbstractInsnNode, BasicBlock> entry : insnToBB.entrySet()) {
        // Basic block 'bb' starts at instruction 'insn'
        AbstractInsnNode insn = entry.getKey();
        BasicBlock bb = entry.getValue();

        // Get the entry blocks for this basic block
        Set<Map.Entry<DataBlock, LabelNode>> pairs = bb.blockLabelSet();
        int remaining = pairs.size();
        LabelNode realStuff = null;//  www . j  a v  a 2s. c  o  m
        if (remaining > 1) {
            // There are two or more entries to this block.
            // We will need a label to jump over the other entries.
            realStuff = new LabelNode();
        }
        // any fallen into entry blocks must be instrumented first (no label
        // switching was done for them.
        DataBlock fallenInto = bb.fallenInto();
        if (fallenInto != null) {
            assert (bb.getLabel(fallenInto) == null);
            instructions.insertBefore(insn,
                    Instrumenter.instrumentation(fallenInto, params.isDetectInternal()));
            if (--remaining > 0) {
                // jump over the next instrumentation of this basic block
                instructions.insertBefore(insn, new JumpInsnNode(GOTO, realStuff));
            }
        }

        // Process the other entry blocks
        for (Map.Entry<DataBlock, LabelNode> pair : pairs) {
            DataBlock block = pair.getKey();
            if (!block.isFallenInto()) {
                // insert the label
                LabelNode lnode = pair.getValue();
                assert (lnode != null);

                // insert created label
                instructions.insertBefore(insn, lnode);

                // insert the instrumentation
                instructions.insertBefore(insn, Instrumenter.instrumentation(block, params.isDetectInternal()));
                if (--remaining > 0) {
                    // jump over the next instrumentation of this basic block
                    instructions.insertBefore(insn, new JumpInsnNode(GOTO, realStuff));
                }
            }
        }
        if (realStuff != null) {
            // insert label for the real code
            instructions.insertBefore(insn, realStuff);
        }

        assert (remaining == 0);
    }
}

From source file:com.triage.bytecodemaster.TestObjectReferenceSwitches.java

public void testReplacingThisWithOtherVariable() throws Exception {

    final String FIELDPROXYWORKED = "FIELDPROXYWORKED";

    //set up the proxy object. this is the object that will receive
    //the proxied calls
    TestSubClass tcc = new TestSubClass();
    tcc.setBaseString(FIELDPROXYWORKED);

    TestBaseClassHolder.setTestBase(tcc);

    //get the dynamic source that has the donor body in it
    ClassNode donorSource = loadGroovyTestClassAsBytecode(GROOVY_CLASS_FIELDREF);
    MethodNode donorMethod = findMethod(donorSource, "before_whatDoIThinkAbout");

    System.out.println("Donor");
    printMethodNode(donorMethod);//from w ww .j a va2s  .  co m

    //alright here's the strategy:  (1) inject a new local variable that points 
    //   to our remote instance,
    //  (2) inject code that sets this local to the value of a method call,
    //  (3) change references to 'this' ( ALOAD0 or ALOAD 0 ) to ALOAD1

    InsnList instructionsToInject = donorMethod.instructions;

    //make a new local variable
    LabelNode begin = new LabelNode();
    LabelNode end = new LabelNode();
    instructionsToInject.insertBefore(instructionsToInject.getFirst(), begin);
    instructionsToInject.add(end);

    Type type = Type.getObjectType("com/triage/bytecodemaster/fortesting/TestBaseClass");
    int variableIndex = donorMethod.maxLocals;
    donorMethod.maxLocals += type.getSize();
    donorMethod.visitLocalVariable("proxy", type.getDescriptor(), null, begin.getLabel(), end.getLabel(),
            variableIndex);

    //set the value of the local variable with a new instruction at the top
    //fetch a reference to our proxy object
    MethodInsnNode getTestBase = new MethodInsnNode(Opcodes.INVOKESTATIC,
            "com/triage/bytecodemaster/fortesting/TestBaseClassHolder", "getTestBase",
            "()Lcom/triage/bytecodemaster/fortesting/TestBaseClass;");

    //insert after begin label
    instructionsToInject.insert(begin, getTestBase);

    //store reference
    VarInsnNode setRef = new VarInsnNode(Opcodes.ASTORE, variableIndex);

    //insert store after fetch
    instructionsToInject.insert(getTestBase, setRef);

    //replace all references to 'this'  with the new variable

    for (int currentIndex = 0; currentIndex < instructionsToInject.size(); currentIndex++) {
        AbstractInsnNode node = instructionsToInject.get(currentIndex);
        if (node.getOpcode() == Opcodes.ALOAD) {
            VarInsnNode vin = (VarInsnNode) node;

            //'this' is var index 0. ours is var index varindex
            if (vin.var == 0) {
                vin.var = variableIndex;
            }
        }
    }

    System.out.println(">>>>>>>>>Finished Modifying<<<<<<<<");
    printMethodNode(donorMethod);
    String NEWCLASSNAME = "ScriptTestClass";

    //write a class 
    Class c = createClassFromClassNode(donorSource, NEWCLASSNAME);

    Object o = c.newInstance();
    Method m = o.getClass().getDeclaredMethod("before_whatDoIThinkAbout", String.class);

    //should return HAHAHA not baseStringValue 
    String result = (String) m.invoke(o, new Object[] { "AAAA" });
    System.out.println("TestDonorClass.whatDoIThinkAbout Result: " + result);
    assertTrue(result.equals(FIELDPROXYWORKED + "AAAA"));
}

From source file:com.triage.bytecodemaster.TestObjectReferenceSwitches.java

@Test
public void testInjectingIntoMethodWithLotsOfParameters() throws Exception {
    final String FIELDPROXYWORKED = "FIELDPROXYWORKED";

    //set up the proxy object. this is the object that will receive
    //the proxied calls
    TestSubClass tcc = new TestSubClass();
    tcc.setBaseString(FIELDPROXYWORKED);

    TestBaseClassHolder.setTestBase(tcc);

    //get the dynamic source that has the donor body in it
    ClassNode donorSource = loadGroovyTestClassAsBytecode(GROOVY_CLASS_FIELDREF2);
    MethodNode donorMethod = findMethod(donorSource, "before_whatDoIThinkAbout");

    System.out.println("Donor Method Before Modifications:");
    printMethodNode(donorMethod);/*from   w w w.  jav  a  2 s .c  o m*/

    String TARGETCLASSNAME = "com.triage.bytecodemaster.fortesting.Concatenator";
    ClassNode targetSource = loadLocalClass(TARGETCLASSNAME);

    ClassNode exampleSource = loadLocalClass("com.triage.bytecodemaster.fortesting.JustLikeGroovyClass");
    MethodNode exampleMethod = findMethod(exampleSource, "before_whatDoIThinkAbout");

    System.out.println("Example Method-- Should be just like the Donor Source");
    printMethodNode(exampleMethod);
    MethodNode targetMethod = findMethod(targetSource, "concat");
    System.out.println("Target Method <Before Mods>");
    printMethodNode(targetMethod);

    //alright here's the strategy:  (1) inject a new local variable that points 
    //   to our remote instance,
    //  (2) inject code that sets this local to the value of a method call,
    //  (3) change references to 'this' ( ALOAD0 or ALOAD 0 ) to ALOAD1

    InsnList instructionsToInject = donorMethod.instructions;
    InsnList targetInstructions = targetMethod.instructions;

    //make a new local variable in the donor method.
    //this variable needs to have a slot high enough that it doesnt
    //conflict with either the target or the source method
    //it will hold references to the objects we replace with 'this'
    LabelNode begin = new LabelNode();
    LabelNode end = new LabelNode();
    targetInstructions.insertBefore(targetInstructions.getFirst(), begin);
    targetInstructions.add(end);

    Type type = Type.getObjectType("com/triage/bytecodemaster/fortesting/TestBaseClass");
    int variableIndex = targetMethod.maxLocals;
    targetMethod.maxLocals += type.getSize();
    targetMethod.visitLocalVariable("proxy", type.getDescriptor(), null, begin.getLabel(), end.getLabel(),
            variableIndex);

    //set the value of the local variable with a new instruction at the top
    //fetch a reference to our proxy object
    MethodInsnNode getTestBase = new MethodInsnNode(Opcodes.INVOKESTATIC,
            "com/triage/bytecodemaster/fortesting/TestBaseClassHolder", "getTestBase",
            "()Lcom/triage/bytecodemaster/fortesting/TestBaseClass;");

    //insert after begin label
    targetInstructions.insert(begin, getTestBase);

    //store reference
    VarInsnNode setRef = new VarInsnNode(Opcodes.ASTORE, variableIndex);

    //insert store after fetch
    targetInstructions.insert(getTestBase, setRef);

    //replace all references to 'this' in the DONOR method with the new variable
    //in the TARGET code

    for (int currentIndex = 0; currentIndex < instructionsToInject.size(); currentIndex++) {
        AbstractInsnNode node = instructionsToInject.get(currentIndex);
        if (node.getOpcode() == Opcodes.ALOAD) {
            VarInsnNode vin = (VarInsnNode) node;

            //'this' is var index 0. ours is var index varindex
            if (vin.var == 0) {
                vin.var = variableIndex;
            }
        }

        //remove return methods. this will prevent a return. it should cause the donor 
        //method to have parameters that overlap with the target, which has more parameters
        if (node.getOpcode() == Opcodes.RETURN || node.getOpcode() == Opcodes.ARETURN) {
            instructionsToInject.remove(node);
        }
    }

    System.out.println(">>>>>>>>>Finished Modifying Donor Method <<<<<<<<");
    printMethodNode(donorMethod);
    String NEWCLASSNAME = "ScriptTestClass";

    //stash instructions at the beginning of the original method, 
    //but after populating the new variable
    targetInstructions.insert(setRef, instructionsToInject);

    System.out.println("Modified Target:");
    printMethodNode(targetMethod);

    //write a class 
    Class c = createClassFromClassNode(targetSource, TARGETCLASSNAME);

    Object o = c.newInstance();
    Method m = o.getClass().getDeclaredMethod("concat", String.class, String.class, String.class, String.class);

    //should return HAHAHA not baseStringValue 
    String result = (String) m.invoke(o, new Object[] { "A", "B", "C", "D" });
    System.out.println("Concatenator.concat Result: " + result);
    assertTrue(result.equals("ABCD"));

}

From source file:com.triage.bytecodemaster.TestObjectReferenceSwitches.java

public void testMergedInReplacingThisWithOtherVariable() throws Exception {

    final String FIELDPROXYWORKED = "FIELDPROXYWORKED";

    //set up the proxy object. this is the object that will receive
    //the proxied calls
    TestSubClass tcc = new TestSubClass();
    tcc.setBaseString(FIELDPROXYWORKED);

    TestBaseClassHolder.setTestBase(tcc);

    //get the dynamic source that has the donor body in it
    ClassNode donorSource = loadGroovyTestClassAsBytecode(GROOVY_CLASS_FIELDREF);
    MethodNode donorMethod = findMethod(donorSource, "before_whatDoIThinkAbout");

    //load the target class
    String TARGETCLASSNAME = "com.triage.bytecodemaster.fortesting.TestFriend";
    ClassNode targetSource = loadLocalClass(TARGETCLASSNAME);
    MethodNode targetMethod = findMethod(targetSource, "whatDoIThinkAbout");

    System.out.println("Target");
    printMethodNode(targetMethod);/*from w  w w  . ja v a 2s . co m*/

    System.out.println("Donor");
    printMethodNode(donorMethod);

    //alright here's the strategy:  (1) inject a new local variable that points 
    //   to our remote instance,
    //  (2) inject code that sets this local to the value of a method call,
    //  (3) change references to 'this' ( ALOAD0 or ALOAD 0 ) to ALOAD1

    InsnList instructionsToInject = donorMethod.instructions;

    //make a new local variable
    LabelNode begin = new LabelNode();
    LabelNode end = new LabelNode();
    instructionsToInject.insertBefore(instructionsToInject.getFirst(), begin);
    instructionsToInject.add(end);

    Type type = Type.getObjectType("com/triage/bytecodemaster/fortesting/TestBaseClass");
    int variableIndex = donorMethod.maxLocals;
    donorMethod.maxLocals += type.getSize();
    donorMethod.visitLocalVariable("proxy", type.getDescriptor(), null, begin.getLabel(), end.getLabel(),
            variableIndex);

    //set the value of the local variable with a new instruction at the top
    //fetch a reference to our proxy object
    MethodInsnNode getTestBase = new MethodInsnNode(Opcodes.INVOKESTATIC,
            "com/triage/bytecodemaster/fortesting/TestBaseClassHolder", "getTestBase",
            "()Lcom/triage/bytecodemaster/fortesting/TestBaseClass;");

    //insert after begin label
    instructionsToInject.insert(begin, getTestBase);

    //store reference
    VarInsnNode setRef = new VarInsnNode(Opcodes.ASTORE, variableIndex);

    //insert store after fetch
    instructionsToInject.insert(getTestBase, setRef);

    //replace all references to 'this'  with the new variable

    for (int currentIndex = 0; currentIndex < instructionsToInject.size(); currentIndex++) {
        AbstractInsnNode node = instructionsToInject.get(currentIndex);
        if (node.getOpcode() == Opcodes.ALOAD) {
            VarInsnNode vin = (VarInsnNode) node;

            //'this' is var index 0. ours is var index varindex
            if (vin.var == 0) {
                vin.var = variableIndex;
            }
        }
    }

    System.out.println(">>>>>>>>>Finished Modifying<<<<<<<<");
    printMethodNode(donorMethod);

    //insert the donorMethod
    targetMethod.instructions.insert(instructionsToInject);

    System.out.println(">>>>>>>>>Final Method<<<<<<<<");
    printMethodNode(targetMethod);

    //write a class 
    Class c = createClassFromClassNode(targetSource, TARGETCLASSNAME);

    Object o = c.newInstance();
    Method m = o.getClass().getDeclaredMethod("whatDoIThinkAbout", TestPerson.class);
    TestPerson testPerson = new TestPerson();
    testPerson.setName("AAAA");
    //should return HAHAHA not baseStringValue 
    String result = (String) m.invoke(o, new Object[] { testPerson });
    System.out.println("TestFriend.whatDoIThinkAbout Result: " + result);
    assertTrue(result.equals(FIELDPROXYWORKED + "AAAA"));
}

From source file:com.typesafe.path_hole.PathHole.java

License:Open Source License

private static byte[] prependToClassLoader() {
    Object[] ourEnhancementsToLoadClass = getMethodNode(PathHole.class, "bytecodeToPrepend",
            "(Ljava/lang/String;Z)V");
    Object[] jlClassLoader = getMethodNode(ClassLoader.class, "loadClass",
            "(Ljava/lang/String;Z)Ljava/lang/Class;");

    // get the bytecode to prepend
    InsnList prependInst = ((MethodNode) ourEnhancementsToLoadClass[1]).instructions;

    // lets get rid of the return statement
    // remove the optional label
    if (prependInst.getLast().getOpcode() < 0) {
        prependInst.remove(prependInst.getLast());
    }/*w w w  .ja va 2  s. co m*/
    // remove the return inst. It doesn't take any args so this is all we need
    prependInst.remove(prependInst.getLast());

    // now add this to loadClass method of jlClassLoader
    InsnList baseInst = ((MethodNode) jlClassLoader[1]).instructions;
    baseInst.insertBefore(baseInst.getFirst(), prependInst);

    ClassNode clClassNode = (ClassNode) jlClassLoader[0];
    //        we just need to add any fields referenced by the prepended bytecode to the jlClassLoader
    //        ClassNode prependClassNode = (ClassNode) ourEnhancementsToLoadClass[0];

    // write the new bytecode
    ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
    clClassNode.accept(cw);
    return cw.toByteArray();
}

From source file:de.tuberlin.uebb.jbop.optimizer.array.LocalArrayLengthInliner.java

License:Open Source License

@Override
protected boolean handleValues(final InsnList original, final Map<Integer, Object> knownArrays,
        final AbstractInsnNode currentNode) {
    if (!NodeHelper.isArrayLength(currentNode)) {
        return false;
    }/*  w w w  .  ja v a2s .  c o m*/

    AbstractInsnNode previous = NodeHelper.getPrevious(currentNode);
    final List<AbstractInsnNode> toBeRemoved = new ArrayList<>();
    int index2 = 0;
    while ((previous != null) && !NodeHelper.isAload(previous)) {
        if (NodeHelper.isAAload(previous)) {
            index2 += 1;
        }
        toBeRemoved.add(previous);
        previous = NodeHelper.getPrevious(previous);
    }
    final int index;
    if ((previous != null) && NodeHelper.isAload(previous)) {
        toBeRemoved.add(previous);
        index = ((VarInsnNode) previous).var;
    } else {
        return false;
    }

    final Object array = knownArrays.get(Integer.valueOf(index));
    if ((array == null)) {
        return false;
    }
    Object array2 = array;
    for (int i = 0; i < index2; ++i) {
        array2 = Array.get(array2, i);
    }
    final int arrayLength = Array.getLength(array2);
    original.insertBefore(currentNode, NodeHelper.getInsnNodeFor(arrayLength));

    for (final AbstractInsnNode remove : toBeRemoved) {
        original.remove(remove);
    }
    original.remove(currentNode);
    return true;
}