Search in sources :

Example 26 with InstructionList

use of org.apache.bcel.generic.InstructionList in project jop by jop-devel.

the class InstructionInterpreter method interpret.

public void interpret(InstructionHandle entry, boolean initialize) {
    // TODO we could use the CFG instead if it exists ?
    InstructionList il = methodInfo.getCode().getInstructionList(true, false);
    Map<InstructionHandle, T> start = new HashMap<InstructionHandle, T>(1);
    start.put(entry, initialize ? analysis.initial(entry) : analysis.bottom());
    interpret(il, start, initialize);
}
Also used : RET(org.apache.bcel.generic.RET) HashMap(java.util.HashMap) InstructionList(org.apache.bcel.generic.InstructionList) InstructionHandle(org.apache.bcel.generic.InstructionHandle)

Example 27 with InstructionList

use of org.apache.bcel.generic.InstructionList in project jop by jop-devel.

the class MethodInfo method updateMethodCode.

private void updateMethodCode() {
    if (!isAbstract() && !isNative()) {
        if (methodCode == null) {
            if (methodGen.getInstructionList() == null) {
                methodGen.setInstructionList(new InstructionList());
            }
            methodCode = new MethodCode(this);
        }
    } else {
        if (methodCode != null) {
            methodGen.setInstructionList(null);
            methodGen.removeCodeAttributes();
            methodGen.removeLineNumbers();
            methodGen.removeExceptionHandlers();
            methodGen.removeLocalVariables();
            methodCode = null;
        }
    }
}
Also used : InstructionList(org.apache.bcel.generic.InstructionList)

Example 28 with InstructionList

use of org.apache.bcel.generic.InstructionList in project jop by jop-devel.

the class ReplaceNativeAndCPIdx method replace.

private Method replace(Method method) {
    MethodGen mg = new MethodGen(method, clazz.getClassName(), cpoolgen);
    InstructionList il = mg.getInstructionList();
    InstructionFinder f = new InstructionFinder(il);
    String methodId = method.getName() + method.getSignature();
    OldMethodInfo mi = getCli().getMethodInfo(methodId);
    // find invokes first and replace call to Native by
    // JOP native instructions.
    String invokeStr = "InvokeInstruction";
    for (Iterator i = f.search(invokeStr); i.hasNext(); ) {
        InstructionHandle[] match = (InstructionHandle[]) i.next();
        InstructionHandle first = match[0];
        InvokeInstruction ii = (InvokeInstruction) first.getInstruction();
        if (ii.getClassName(cpoolgen).equals(JOPizer.nativeClass)) {
            short opid = (short) JopInstr.getNative(ii.getMethodName(cpoolgen));
            if (opid == -1) {
                System.err.println(method.getName() + ": cannot locate " + ii.getMethodName(cpoolgen) + ". Replacing with NOP.");
                first.setInstruction(new NOP());
            } else {
                first.setInstruction(new NativeInstruction(opid, (short) 1));
                ((JOPizer) ai).outTxt.println("\t" + first.getPosition());
                // then we remove pc+2 and pc+1 from the MGCI info
                if (JOPizer.dumpMgci) {
                    il.setPositions();
                    int pc = first.getPosition();
                    // important: take the high one first
                    GCRTMethodInfo.removePC(pc + 2, mi);
                    GCRTMethodInfo.removePC(pc + 1, mi);
                }
            }
        }
        if (ii instanceof INVOKESPECIAL) {
            // not an initializer
            if (!ii.getMethodName(cpoolgen).equals("<init>")) {
                // check if this is a super invoke
                // TODO this is just a hack, use InvokeSite.isInvokeSuper() when this is ported to the new framework!
                boolean isSuper = false;
                String declaredType = ii.getClassName(cpoolgen);
                JopClassInfo cls = getCli();
                OldClassInfo superClass = cls.superClass;
                while (superClass != null) {
                    if (superClass.clazz.getClassName().equals(declaredType)) {
                        isSuper = true;
                        break;
                    }
                    if ("java.lang.Object".equals(superClass.clazz.getClassName())) {
                        break;
                    }
                    superClass = superClass.superClass;
                }
                if (isSuper) {
                    Integer idx = ii.getIndex();
                    int new_index = getCli().cpoolUsed.indexOf(idx) + 1;
                    first.setInstruction(new JOPSYS_INVOKESUPER((short) new_index));
                // System.err.println("invokesuper "+ii.getClassName(cpoolgen)+"."+ii.getMethodName(cpoolgen));
                }
            }
        }
    }
    if (JOPizer.CACHE_INVAL) {
        f = new InstructionFinder(il);
        // find volatile reads and insert cache invalidation bytecode
        String fieldInstr = "GETFIELD|GETSTATIC|PUTFIELD|PUTSTATIC";
        for (Iterator i = f.search(fieldInstr); i.hasNext(); ) {
            InstructionHandle[] match = (InstructionHandle[]) i.next();
            InstructionHandle ih = match[0];
            FieldInstruction fi = (FieldInstruction) ih.getInstruction();
            JavaClass jc = JOPizer.jz.cliMap.get(fi.getClassName(cpoolgen)).clazz;
            Field field = null;
            while (field == null) {
                Field[] fields = jc.getFields();
                for (int k = 0; k < fields.length; k++) {
                    if (fields[k].getName().equals(fi.getFieldName(cpoolgen))) {
                        field = fields[k];
                        break;
                    }
                }
                if (field == null) {
                    try {
                        jc = jc.getSuperClass();
                    } catch (ClassNotFoundException e) {
                        e.printStackTrace();
                        throw new Error();
                    }
                }
            }
            if (field.isVolatile()) {
                if (field.getType().getSize() < 2) {
                    if (fi instanceof GETFIELD || fi instanceof GETSTATIC) {
                        ih.setInstruction(new InvalidateInstruction());
                        ih = il.append(ih, fi);
                    }
                } else {
                    // this only works because we do not throw a
                    // NullPointerException for monitorenter/-exit!
                    ih.setInstruction(new ACONST_NULL());
                    ih = il.append(ih, new MONITORENTER());
                    ih = il.append(ih, fi);
                    ih = il.append(ih, new ACONST_NULL());
                    ih = il.append(ih, new MONITOREXIT());
                }
            }
        }
    }
    f = new InstructionFinder(il);
    // find instructions that access the constant pool
    // and replace the index by the new value from ClassInfo
    String cpInstr = "CPInstruction";
    for (Iterator it = f.search(cpInstr); it.hasNext(); ) {
        InstructionHandle[] match = (InstructionHandle[]) it.next();
        InstructionHandle ih = match[0];
        CPInstruction cpii = (CPInstruction) ih.getInstruction();
        int index = cpii.getIndex();
        // we have to grab the information before we change
        // the CP index.
        FieldInstruction fi = null;
        Type ft = null;
        if (cpii instanceof FieldInstruction) {
            fi = (FieldInstruction) ih.getInstruction();
            ft = fi.getFieldType(cpoolgen);
        }
        Integer idx = new Integer(index);
        // pos is the new position in the reduced constant pool
        // idx is the position in the 'original' unresolved cpool
        int pos = getCli().cpoolUsed.indexOf(idx);
        int new_index = pos + 1;
        // and putfield and by address for getstatic and putstatic
        if (cpii instanceof GETFIELD || cpii instanceof PUTFIELD || cpii instanceof GETSTATIC || cpii instanceof PUTSTATIC) {
            // we use the offset instead of the CP index
            new_index = getFieldOffset(cp, index);
        } else {
            if (pos == -1) {
                System.out.println("Error: constant " + index + " " + cpoolgen.getConstant(index) + " not found");
                System.out.println("new cpool: " + getCli().cpoolUsed);
                System.out.println("original cpool: " + cpoolgen);
                System.exit(-1);
            }
        }
        // set new index, position starts at
        // 1 as cp points to the length of the pool
        cpii.setIndex(new_index);
        if (cpii instanceof FieldInstruction) {
            boolean isRef = ft instanceof ReferenceType;
            boolean isLong = ft == BasicType.LONG || ft == BasicType.DOUBLE;
            if (fi instanceof GETSTATIC) {
                if (isRef) {
                    ih.setInstruction(new GETSTATIC_REF((short) new_index));
                } else if (isLong) {
                    ih.setInstruction(new GETSTATIC_LONG((short) new_index));
                }
            } else if (fi instanceof PUTSTATIC) {
                if (isRef) {
                    if (!com.jopdesign.build.JOPizer.USE_RTTM) {
                        ih.setInstruction(new PUTSTATIC_REF((short) new_index));
                    }
                } else if (isLong) {
                    ih.setInstruction(new PUTSTATIC_LONG((short) new_index));
                }
            } else if (fi instanceof GETFIELD) {
                if (isRef) {
                    ih.setInstruction(new GETFIELD_REF((short) new_index));
                } else if (isLong) {
                    ih.setInstruction(new GETFIELD_LONG((short) new_index));
                }
            } else if (fi instanceof PUTFIELD) {
                if (isRef) {
                    if (!com.jopdesign.build.JOPizer.USE_RTTM) {
                        ih.setInstruction(new PUTFIELD_REF((short) new_index));
                    }
                } else if (isLong) {
                    ih.setInstruction(new PUTFIELD_LONG((short) new_index));
                }
            }
        }
    }
    Method m = mg.getMethod();
    il.dispose();
    return m;
}
Also used : InstructionList(org.apache.bcel.generic.InstructionList) InstructionFinder(org.apache.bcel.util.InstructionFinder) MONITORENTER(org.apache.bcel.generic.MONITORENTER) MethodGen(org.apache.bcel.generic.MethodGen) InstructionHandle(org.apache.bcel.generic.InstructionHandle) ReferenceType(org.apache.bcel.generic.ReferenceType) PUTSTATIC(org.apache.bcel.generic.PUTSTATIC) Field(org.apache.bcel.classfile.Field) CPInstruction(org.apache.bcel.generic.CPInstruction) Iterator(java.util.Iterator) MONITOREXIT(org.apache.bcel.generic.MONITOREXIT) ACONST_NULL(org.apache.bcel.generic.ACONST_NULL) PUTFIELD(org.apache.bcel.generic.PUTFIELD) Method(org.apache.bcel.classfile.Method) INVOKESPECIAL(org.apache.bcel.generic.INVOKESPECIAL) NOP(org.apache.bcel.generic.NOP) InvokeInstruction(org.apache.bcel.generic.InvokeInstruction) GETFIELD(org.apache.bcel.generic.GETFIELD) ReferenceType(org.apache.bcel.generic.ReferenceType) Type(org.apache.bcel.generic.Type) BasicType(org.apache.bcel.generic.BasicType) ConstantNameAndType(org.apache.bcel.classfile.ConstantNameAndType) JavaClass(org.apache.bcel.classfile.JavaClass) FieldInstruction(org.apache.bcel.generic.FieldInstruction) GETSTATIC(org.apache.bcel.generic.GETSTATIC)

Example 29 with InstructionList

use of org.apache.bcel.generic.InstructionList in project jop by jop-devel.

the class MethodCode method replace.

/**
     * Replace instructions in this code with an instruction list or a part of it.
     * If the number of instructions to replace differs from the number of source instructions, instruction
     * handles will be removed or inserted appropriately and the targets will be updated.
     * <p>
     *     Instruction handles will be reused, so attached values and targets will not be lost if the new length is not
     *     shorter than the old length. Else instruction handles are removed and the targeters to removed instructions
     *     are updated to the instruction after the next instruction after the deleted instructions.
     * </p>
     *
     * @param replaceStart the first instruction in this code to replace
     * @param replaceCount the number of instructions in this code to replace
     * @param sourceInfo the MethodInfo containing the source instruction. If non-null, the instructions will be copied
     *                   using the constant pool from the given MethodInfo. If null, the instructions will not be copied.
     * @param sourceStart the first instruction in the source list to use for replacing the code.
     * @param sourceCount the number of instructions to use from the source.
     * @param copyCustomValues if true copy the custom values from the source.
     * @return the first handle in the target list after the inserted code, or null if the last instruction in this
     *         list has been replaced.
     */
public InstructionHandle replace(InstructionHandle replaceStart, int replaceCount, MethodInfo sourceInfo, InstructionHandle sourceStart, int sourceCount, boolean copyCustomValues) {
    InstructionList il = getInstructionList();
    InstructionHandle current = replaceStart;
    InstructionHandle currSource = sourceStart;
    // update the common prefix
    int cnt = Math.min(replaceCount, sourceCount);
    for (int i = 0; i < cnt; i++) {
        Instruction instr;
        if (sourceInfo != null) {
            instr = copyFrom(sourceInfo.getClassInfo(), currSource.getInstruction());
        } else {
            instr = currSource.getInstruction();
        }
        // TODO support branch instructions! need to replace the IH too
        current.setInstruction(instr);
        if (copyCustomValues) {
            copyCustomValues(sourceInfo, current, currSource);
        }
        current = current.getNext();
        currSource = currSource.getNext();
    }
    InstructionHandle next = current;
    // Case 1: delete unused handles, update targets to next instruction
    if (replaceCount > sourceCount) {
        int rest = replaceCount - sourceCount;
        for (int i = 1; i < rest; i++) {
            next = next.getNext();
        }
        InstructionHandle end = next;
        next = next.getNext();
        try {
            // we cannot use next.getPrev, since next might be null
            il.delete(current, end);
        } catch (TargetLostException e) {
            retarget(e, next);
        }
    }
    // Case 2: insert new handles for rest of source
    if (replaceCount < sourceCount) {
        int rest = sourceCount - replaceCount;
        for (int i = 0; i < rest; i++) {
            Instruction instr;
            if (sourceInfo != null) {
                instr = copyFrom(sourceInfo.getClassInfo(), currSource.getInstruction());
            } else {
                instr = currSource.getInstruction();
            }
            if (next == null) {
                current = il.append(instr);
            } else {
                current = il.insert(next, instr);
            }
            if (copyCustomValues) {
                copyCustomValues(sourceInfo, current, currSource);
            }
            currSource = currSource.getNext();
        }
    }
    return next;
}
Also used : InstructionList(org.apache.bcel.generic.InstructionList) InvokeInstruction(org.apache.bcel.generic.InvokeInstruction) Instruction(org.apache.bcel.generic.Instruction) FieldInstruction(org.apache.bcel.generic.FieldInstruction) CPInstruction(org.apache.bcel.generic.CPInstruction) TargetLostException(org.apache.bcel.generic.TargetLostException) InstructionHandle(org.apache.bcel.generic.InstructionHandle)

Example 30 with InstructionList

use of org.apache.bcel.generic.InstructionList in project jop by jop-devel.

the class KeyManager method clearAllValues.

public void clearAllValues(CustomKey key, ClassInfo classInfo) {
    boolean fromStruct = key.getType().isStruct();
    boolean fromCode = key.getType().isCode();
    if (fromStruct) {
        classInfo.removeCustomValue(key);
        for (FieldInfo field : classInfo.getFields()) {
            field.removeCustomValue(key);
        }
    }
    for (MethodInfo method : classInfo.getMethods()) {
        if (fromStruct) {
            method.removeCustomValue(key);
        }
        if (fromCode && method.hasCode()) {
            MethodCode code = method.getCode();
            InstructionList il = code.getInstructionList();
            for (InstructionHandle ih : il.getInstructionHandles()) {
                code.clearCustomKey(ih, key);
            }
        }
    }
}
Also used : InstructionList(org.apache.bcel.generic.InstructionList) InstructionHandle(org.apache.bcel.generic.InstructionHandle)

Aggregations

InstructionList (org.apache.bcel.generic.InstructionList)37 InstructionHandle (org.apache.bcel.generic.InstructionHandle)27 Iterator (java.util.Iterator)9 MethodGen (org.apache.bcel.generic.MethodGen)8 Instruction (org.apache.bcel.generic.Instruction)7 InvokeInstruction (org.apache.bcel.generic.InvokeInstruction)7 Type (org.apache.bcel.generic.Type)7 InstructionFinder (org.apache.bcel.util.InstructionFinder)7 MethodCode (com.jopdesign.common.MethodCode)6 CPInstruction (org.apache.bcel.generic.CPInstruction)6 ConstantPoolGen (org.apache.bcel.generic.ConstantPoolGen)6 FieldInstruction (org.apache.bcel.generic.FieldInstruction)6 MethodInfo (com.jopdesign.common.MethodInfo)5 NOP (org.apache.bcel.generic.NOP)5 BranchInstruction (org.apache.bcel.generic.BranchInstruction)4 ReturnInstruction (org.apache.bcel.generic.ReturnInstruction)4 ClassInfo (com.jopdesign.common.ClassInfo)3 InvokeSite (com.jopdesign.common.code.InvokeSite)3 Constant (org.apache.bcel.classfile.Constant)3 JavaClass (org.apache.bcel.classfile.JavaClass)3