Search in sources :

Example 66 with InstructionHandle

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

the class CFGCallgraphBuilder method findInvokeSites.

@Override
protected Set<InvokeSite> findInvokeSites(MethodCode code) {
    ControlFlowGraph cfg = code.getControlFlowGraph(false);
    Set<InvokeSite> invokeSites = new LinkedHashSet<InvokeSite>();
    // Basic blocks however are not removed from the block list..
    for (CFGNode node : cfg.vertexSet()) {
        BasicBlock bb = node.getBasicBlock();
        if (bb == null)
            continue;
        // but hey, invokeSites is a set anyway..
        for (InstructionHandle ih : bb.getInstructions()) {
            if (code.isInvokeSite(ih)) {
                invokeSites.add(code.getInvokeSite(ih));
            }
        }
    }
    return invokeSites;
}
Also used : LinkedHashSet(java.util.LinkedHashSet) CFGNode(com.jopdesign.common.code.ControlFlowGraph.CFGNode) InstructionHandle(org.apache.bcel.generic.InstructionHandle)

Example 67 with InstructionHandle

use of org.apache.bcel.generic.InstructionHandle 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 68 with InstructionHandle

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

the class MethodCode method getLineNumber.

/**
     * Get the line number of the instruction. This may refer to a line number in another file.
     * To get the correct source file for this instruction, use {@link #getSourceFileName(InstructionHandle)}.
     *
     * @see #getSourceFileName(InstructionHandle)
     * @param ih the instruction to check.
     * @return the line number of the instruction, or -1 if unknown.
     */
public int getLineNumber(InstructionHandle ih) {
    InstructionHandle handle = findLineNumberHandle(ih);
    if (handle == null)
        return -1;
    Integer line = (Integer) handle.getAttribute(KEY_LINENUMBER);
    if (line != null) {
        return line;
    }
    LineNumberGen entry = getLineNumberEntry(handle, false);
    return entry != null ? entry.getSourceLine() : -1;
}
Also used : LineNumberGen(org.apache.bcel.generic.LineNumberGen) InstructionHandle(org.apache.bcel.generic.InstructionHandle)

Example 69 with InstructionHandle

use of org.apache.bcel.generic.InstructionHandle 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 70 with InstructionHandle

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

the class MethodCode method getLineString.

public String getLineString(InstructionHandle ih) {
    InstructionHandle handle = findLineNumberHandle(ih);
    if (handle == null) {
        return "<none>";
    }
    String className = getSourceClassAttribute(handle);
    if (className != null) {
        return className + ":" + getLineNumber(handle);
    }
    LineNumberGen lg = getLineNumberEntry(handle, false);
    return String.valueOf(lg.getSourceLine());
}
Also used : LineNumberGen(org.apache.bcel.generic.LineNumberGen) HashedString(com.jopdesign.common.misc.HashedString) CallString(com.jopdesign.common.code.CallString) InstructionHandle(org.apache.bcel.generic.InstructionHandle)

Aggregations

InstructionHandle (org.apache.bcel.generic.InstructionHandle)103 InstructionList (org.apache.bcel.generic.InstructionList)26 MethodInfo (com.jopdesign.common.MethodInfo)20 CallString (com.jopdesign.common.code.CallString)20 Instruction (org.apache.bcel.generic.Instruction)13 MethodCode (com.jopdesign.common.MethodCode)12 ContextMap (com.jopdesign.dfa.framework.ContextMap)11 IntermediateEdge (org.candle.decompiler.intermediate.graph.edge.IntermediateEdge)11 Context (com.jopdesign.dfa.framework.Context)10 InvokeInstruction (org.apache.bcel.generic.InvokeInstruction)10 Iterator (java.util.Iterator)9 BranchInstruction (org.apache.bcel.generic.BranchInstruction)9 FieldInstruction (org.apache.bcel.generic.FieldInstruction)9 AbstractIntermediate (org.candle.decompiler.intermediate.code.AbstractIntermediate)9 ReturnInstruction (org.apache.bcel.generic.ReturnInstruction)8 InstructionFinder (org.apache.bcel.util.InstructionFinder)8 ClassInfo (com.jopdesign.common.ClassInfo)7 HashMap (java.util.HashMap)7 HashSet (java.util.HashSet)7 LinkedList (java.util.LinkedList)7