Search in sources :

Example 1 with DFATool

use of com.jopdesign.dfa.DFATool in project jop by jop-devel.

the class LoopBounds method transfer.

public ContextMap<CallString, Map<Location, ValueMapping>> transfer(InstructionHandle stmt, FlowEdge edge, ContextMap<CallString, Map<Location, ValueMapping>> input, Interpreter<CallString, Map<Location, ValueMapping>> interpreter, Map<InstructionHandle, ContextMap<CallString, Map<Location, ValueMapping>>> state) {
    Context context = new Context(input.getContext());
    Map<Location, ValueMapping> in = (Map<Location, ValueMapping>) input.get(context.callString);
    ContextMap<CallString, Map<Location, ValueMapping>> retval = new ContextMap<CallString, Map<Location, ValueMapping>>(context, new LinkedHashMap<CallString, Map<Location, ValueMapping>>());
    Instruction instruction = stmt.getInstruction();
    // shortcut for infeasible paths
    if (in == null) {
        context.stackPtr += instruction.produceStack(context.constPool()) - instruction.consumeStack(context.constPool());
        return retval;
    }
    Map<Location, ValueMapping> result = new LinkedHashMap<Location, ValueMapping>();
    retval.put(context.callString, result);
    switch(instruction.getOpcode()) {
        case Constants.ICONST_M1:
        case Constants.ICONST_0:
        case Constants.ICONST_1:
        case Constants.ICONST_2:
        case Constants.ICONST_3:
        case Constants.ICONST_4:
        case Constants.ICONST_5:
        case Constants.BIPUSH:
        case Constants.SIPUSH:
            {
                ConstantPushInstruction instr = (ConstantPushInstruction) instruction;
                result = new LinkedHashMap<Location, ValueMapping>(in);
                retval.put(context.callString, result);
                int value = instr.getValue().intValue();
                result.put(new Location(context.stackPtr), new ValueMapping(value));
            }
            break;
        case Constants.ACONST_NULL:
            result = in;
            retval.put(context.callString, result);
            break;
        case Constants.LDC:
        case Constants.LDC_W:
            {
                LDC instr = (LDC) instruction;
                result = new LinkedHashMap<Location, ValueMapping>(in);
                retval.put(context.callString, result);
                Type type = instr.getType(context.constPool());
                if (type.equals(Type.INT)) {
                    Integer value = (Integer) instr.getValue(context.constPool());
                    result.put(new Location(context.stackPtr), new ValueMapping(value));
                } else if (type.equals(Type.STRING)) {
                    String value = (String) instr.getValue(context.constPool());
                    String name = "char[]";
                    name += "@" + context.method() + ":" + stmt.getPosition();
                    result.put(new Location(name + ".length"), new ValueMapping(value.length()));
                //				System.out.println(name+": \""+value+"\"");				
                }
            }
            break;
        case Constants.LDC2_W:
            result = in;
            retval.put(context.callString, result);
            break;
        case Constants.ISTORE_0:
        case Constants.ISTORE_1:
        case Constants.ISTORE_2:
        case Constants.ISTORE_3:
        case Constants.ISTORE:
            {
                StoreInstruction instr = (StoreInstruction) instruction;
                int index = instr.getIndex();
                for (Location l : in.keySet()) {
                    if (l.stackLoc < context.stackPtr - 1 && l.stackLoc != index) {
                        result.put(l, in.get(l));
                    }
                    if (l.stackLoc == context.stackPtr - 1) {
                        ValueMapping v = new ValueMapping(in.get(l), true);
                        if (in.get(l).source == null || in.get(l).source.stackLoc != index) {
                            v.defscope = ValueMapping.scope;
                        }
                        result.put(new Location(index), v);
                    }
                }
            }
            break;
        case Constants.ASTORE_0:
        case Constants.ASTORE_1:
        case Constants.ASTORE_2:
        case Constants.ASTORE_3:
        case Constants.ASTORE:
            result = in;
            retval.put(context.callString, result);
            break;
        case Constants.LSTORE_0:
        case Constants.LSTORE_1:
        case Constants.LSTORE_2:
        case Constants.LSTORE_3:
        case Constants.LSTORE:
            // drop top entries to avoid clobbering
            filterSet(in, result, context.stackPtr - 2);
            break;
        case Constants.ILOAD_0:
        case Constants.ILOAD_1:
        case Constants.ILOAD_2:
        case Constants.ILOAD_3:
        case Constants.ILOAD:
            {
                LoadInstruction instr = (LoadInstruction) instruction;
                filterSet(in, result, context.stackPtr);
                int index = instr.getIndex();
                for (Location l : in.keySet()) {
                    if (l.stackLoc == index) {
                        ValueMapping m = new ValueMapping(in.get(l), true);
                        m.source = l;
                        result.put(new Location(context.stackPtr), m);
                    }
                }
            }
            break;
        case Constants.ALOAD_0:
        case Constants.ALOAD_1:
        case Constants.ALOAD_2:
        case Constants.ALOAD_3:
        case Constants.ALOAD:
            result = in;
            retval.put(context.callString, result);
            break;
        case Constants.ARRAYLENGTH:
            {
                filterSet(in, result, context.stackPtr - 1);
                DFATool p = interpreter.getDFATool();
                Set<String> receivers = p.getReceivers(stmt, context.callString);
                Location location = new Location(context.stackPtr - 1);
                boolean valid = false;
                if (receivers == null) {
                    System.out.println("no receivers at: " + context.callString.toStringList() + context.method() + stmt);
                } else {
                    for (String arrayName : receivers) {
                        ValueMapping m = in.get(new Location(arrayName + ".length"));
                        if (m != null) {
                            ValueMapping value = new ValueMapping(m, false);
                            value.join(result.get(location));
                            result.put(location, value);
                            valid = true;
                        }
                    }
                }
                if (!valid) {
                    result.put(new Location(context.stackPtr - 1), new ValueMapping());
                }
            }
            break;
        case Constants.PUTFIELD:
            {
                PUTFIELD instr = (PUTFIELD) instruction;
                int fieldSize = instr.getFieldType(context.constPool()).getSize();
                for (Location l : in.keySet()) {
                    if (l.stackLoc >= 0 && l.stackLoc < context.stackPtr - 1 - fieldSize) {
                        result.put(l, in.get(l));
                    }
                }
                //			System.out.println(context.stackPtr+","+fieldSize+": "+result);
                DFATool p = interpreter.getDFATool();
                Set<String> receivers = p.getReceivers(stmt, context.callString);
                if (receivers == null) {
                    warnNoReceiver(context, stmt);
                } else {
                    for (String fieldName : receivers) {
                        String f = fieldName.substring(fieldName.lastIndexOf("."), fieldName.length());
                        String strippedName;
                        if (fieldName.indexOf("@") >= 0) {
                            strippedName = fieldName.split("@")[0] + f;
                        } else {
                            strippedName = fieldName;
                        }
                        if (p.containsField(strippedName)) {
                            for (Location l : in.keySet()) {
                                if (l.stackLoc < 0 && !receivers.contains(l.heapLoc)) {
                                    result.put(l, in.get(l));
                                }
                                if (l.stackLoc == context.stackPtr - 1) {
                                    result.put(new Location(fieldName), new ValueMapping(in.get(l), false));
                                }
                            }
                        }
                    }
                }
            }
            break;
        case Constants.GETFIELD:
            {
                GETFIELD instr = (GETFIELD) instruction;
                filterSet(in, result, context.stackPtr - 1);
                DFATool p = interpreter.getDFATool();
                Set<String> receivers = p.getReceivers(stmt, context.callString);
                Location location = new Location(context.stackPtr - 1);
                boolean valid = false;
                if (receivers == null) {
                    warnNoReceiver(context, stmt);
                } else {
                    for (String fieldName : receivers) {
                        String f = fieldName.substring(fieldName.lastIndexOf("."), fieldName.length());
                        String strippedName;
                        if (fieldName.indexOf("@") >= 0) {
                            strippedName = fieldName.split("@")[0] + f;
                        } else {
                            strippedName = fieldName;
                        }
                        if (p.containsField(strippedName)) {
                            for (Location l : in.keySet()) {
                                if (l.heapLoc.equals(fieldName)) {
                                    ValueMapping value = new ValueMapping(in.get(l), false);
                                    value.join(result.get(location));
                                    result.put(location, value);
                                    valid = true;
                                }
                            }
                        }
                    }
                }
                if (!valid && !(instr.getFieldType(context.constPool()) instanceof ReferenceType)) {
                    result.put(new Location(context.stackPtr - 1), new ValueMapping());
                }
            }
            break;
        case Constants.PUTSTATIC:
            {
                PUTSTATIC instr = (PUTSTATIC) instruction;
                int fieldSize = instr.getFieldType(context.constPool()).getSize();
                for (Location l : in.keySet()) {
                    if (l.stackLoc >= 0 && l.stackLoc < context.stackPtr - fieldSize) {
                        result.put(l, in.get(l));
                    }
                }
                DFATool p = interpreter.getDFATool();
                Set<String> receivers = p.getReceivers(stmt, context.callString);
                for (String fieldName : receivers) {
                    if (p.containsField(fieldName)) {
                        for (Location l : in.keySet()) {
                            if (l.stackLoc < 0 && !receivers.contains(l.heapLoc)) {
                                result.put(l, in.get(l));
                            }
                            if (l.stackLoc == context.stackPtr - 1) {
                                result.put(new Location(fieldName), new ValueMapping(in.get(l), false));
                            }
                        }
                    }
                }
            }
            break;
        case Constants.GETSTATIC:
            {
                GETSTATIC instr = (GETSTATIC) instruction;
                result = new LinkedHashMap<Location, ValueMapping>(in);
                retval.put(context.callString, result);
                DFATool p = interpreter.getDFATool();
                Set<String> receivers = p.getReceivers(stmt, context.callString);
                Location location = new Location(context.stackPtr);
                boolean valid = false;
                for (String fieldName : receivers) {
                    if (p.containsField(fieldName)) {
                        for (Location l : in.keySet()) {
                            if (l.heapLoc.equals(fieldName)) {
                                ValueMapping value = new ValueMapping(in.get(l), false);
                                value.join(result.get(location));
                                result.put(location, value);
                                valid = true;
                            }
                        }
                    }
                }
                if (!valid && !(instr.getFieldType(context.constPool()) instanceof ReferenceType)) {
                    result.put(new Location(context.stackPtr), new ValueMapping());
                }
            }
            break;
        case Constants.IASTORE:
        case Constants.CASTORE:
        case Constants.SASTORE:
        case Constants.BASTORE:
            {
                for (Location l : in.keySet()) {
                    if (l.stackLoc < context.stackPtr - 3) {
                        result.put(l, in.get(l));
                    }
                }
                DFATool p = interpreter.getDFATool();
                Set<String> receivers = p.getReceivers(stmt, context.callString);
                if (receivers == null) {
                    warnNoReceiver(context, stmt);
                    break;
                }
                for (String name : receivers) {
                    for (Location l : in.keySet()) {
                        if (l.stackLoc == context.stackPtr - 1) {
                            Location loc = new Location(name);
                            ValueMapping val = new ValueMapping(in.get(l), false);
                            val.join(in.get(loc));
                            result.put(loc, val);
                        }
                    }
                }
            }
            break;
        case Constants.AASTORE:
            {
                filterSet(in, result, context.stackPtr - 3);
            }
            break;
        case Constants.IALOAD:
        case Constants.CALOAD:
        case Constants.SALOAD:
        case Constants.BALOAD:
            {
                filterSet(in, result, context.stackPtr - 2);
                DFATool p = interpreter.getDFATool();
                Location location = new Location(context.stackPtr - 2);
                boolean valid = false;
                Set<String> receivers = p.getReceivers(stmt, context.callString);
                for (String name : receivers) {
                    for (Location l : in.keySet()) {
                        if (l.heapLoc.equals(name)) {
                            ValueMapping value = new ValueMapping(in.get(l), false);
                            value.join(result.get(location));
                            result.put(location, value);
                            valid = true;
                        }
                    }
                }
                if (!valid) {
                    result.put(new Location(context.stackPtr - 2), new ValueMapping(0));
                }
            }
            break;
        case Constants.AALOAD:
            {
                ValueMapping v = in.get(new Location(context.stackPtr - 1));
                if (v == null) {
                    logger.warn("no value at: " + context.callString.toStringList() + context.method() + stmt);
                } else {
                    recordArrayIndex(stmt, context, v.assigned);
                }
                filterSet(in, result, context.stackPtr - 2);
            }
            break;
        case Constants.DUP:
            {
                for (Location l : in.keySet()) {
                    result.put(l, in.get(l));
                    if (l.stackLoc == context.stackPtr - 1) {
                        result.put(new Location(context.stackPtr), new ValueMapping(in.get(l), true));
                    }
                }
            }
            break;
        case Constants.DUP_X1:
            {
                for (Location l : in.keySet()) {
                    if (l.stackLoc < context.stackPtr - 2) {
                        result.put(l, in.get(l));
                    }
                    if (l.stackLoc == context.stackPtr - 1) {
                        result.put(new Location(context.stackPtr - 2), new ValueMapping(in.get(l), true));
                        result.put(new Location(context.stackPtr), new ValueMapping(in.get(l), true));
                    }
                    if (l.stackLoc == context.stackPtr - 2) {
                        result.put(new Location(context.stackPtr - 1), new ValueMapping(in.get(l), true));
                    }
                }
            }
            break;
        case Constants.DUP2:
            {
                for (Location l : in.keySet()) {
                    result.put(l, in.get(l));
                    if (l.stackLoc == context.stackPtr - 2) {
                        result.put(new Location(context.stackPtr), new ValueMapping(in.get(l), true));
                    }
                    if (l.stackLoc == context.stackPtr - 1) {
                        result.put(new Location(context.stackPtr + 1), new ValueMapping(in.get(l), true));
                    }
                }
            }
            break;
        case Constants.POP:
            {
                filterSet(in, result, context.stackPtr - 1);
            }
            break;
        case Constants.POP2:
            {
                filterSet(in, result, context.stackPtr - 2);
            }
            break;
        case Constants.IINC:
            {
                IINC instr = (IINC) instruction;
                int index = instr.getIndex();
                int increment = instr.getIncrement();
                for (Location l : in.keySet()) {
                    if (l.stackLoc < context.stackPtr) {
                        result.put(l, in.get(l));
                    }
                    if (l.stackLoc == index) {
                        ValueMapping m = new ValueMapping(in.get(l), true);
                        m.assigned.add(increment);
                        m.constrained.add(increment);
                        Interval operand = new Interval(increment, increment);
                        if (m.increment != null && !m.softinc) {
                            m.increment.join(operand);
                        } else if (m.increment != null && m.softinc) {
                            if ((m.increment.getLb() < 0 && operand.getUb() > 0) || (m.increment.getUb() > 0 && operand.getLb() < 0)) {
                                m.increment.join(operand);
                            } else {
                                m.increment = operand;
                            }
                            m.softinc = false;
                        } else {
                            m.increment = operand;
                            m.softinc = false;
                        }
                        result.put(l, m);
                    }
                }
            }
            break;
        case Constants.IADD:
            {
                Interval operand = new Interval();
                for (Location l : in.keySet()) {
                    if (l.stackLoc == context.stackPtr - 1) {
                        operand = in.get(l).assigned;
                    }
                }
                for (Location l : in.keySet()) {
                    if (l.stackLoc < context.stackPtr - 2) {
                        result.put(l, in.get(l));
                    } else if (l.stackLoc == context.stackPtr - 2) {
                        ValueMapping m = new ValueMapping(in.get(l), true);
                        m.assigned.add(operand);
                        m.constrained.add(operand);
                        if (m.increment != null && !m.softinc) {
                            m.increment.join(operand);
                        } else if (m.increment != null && m.softinc) {
                            if ((m.increment.getLb() < 0 && operand.getUb() > 0) || (m.increment.getUb() > 0 && operand.getLb() < 0)) {
                                m.increment.join(operand);
                            } else {
                                m.increment = operand;
                            }
                            m.softinc = false;
                        } else {
                            m.increment = operand;
                            m.softinc = false;
                        }
                        result.put(l, m);
                    }
                }
            }
            break;
        case Constants.ISUB:
            {
                Interval operand = new Interval();
                for (Location l : in.keySet()) {
                    if (l.stackLoc == context.stackPtr - 1) {
                        operand = in.get(l).assigned;
                    }
                }
                for (Location l : in.keySet()) {
                    if (l.stackLoc < context.stackPtr - 2) {
                        result.put(l, in.get(l));
                    } else if (l.stackLoc == context.stackPtr - 2) {
                        ValueMapping m = new ValueMapping(in.get(l), true);
                        m.assigned.sub(operand);
                        m.constrained.sub(operand);
                        // decrement rather than increment
                        operand.neg();
                        if (m.increment != null && !m.softinc) {
                            m.increment.join(operand);
                        } else if (m.increment != null && m.softinc) {
                            if ((m.increment.getLb() < 0 && operand.getUb() > 0) || (m.increment.getUb() > 0 && operand.getLb() < 0)) {
                                m.increment.join(operand);
                            } else {
                                m.increment = operand;
                            }
                            m.softinc = false;
                        } else {
                            m.increment = operand;
                            m.softinc = false;
                        }
                        result.put(l, m);
                    }
                }
            }
            break;
        case Constants.INEG:
            {
                for (Location l : in.keySet()) {
                    if (l.stackLoc < context.stackPtr - 1) {
                        result.put(l, in.get(l));
                    } else if (l.stackLoc == context.stackPtr - 1) {
                        ValueMapping m = new ValueMapping(in.get(l), true);
                        m.assigned.neg();
                        m.constrained.neg();
                        m.increment = new Interval();
                        result.put(l, m);
                    }
                }
            }
            break;
        case Constants.IUSHR:
            {
                Interval operand = new Interval();
                for (Location l : in.keySet()) {
                    if (l.stackLoc == context.stackPtr - 1) {
                        operand = in.get(l).assigned;
                    }
                }
                for (Location l : in.keySet()) {
                    if (l.stackLoc < context.stackPtr - 2) {
                        result.put(l, in.get(l));
                    } else if (l.stackLoc == context.stackPtr - 2) {
                        ValueMapping m = new ValueMapping(in.get(l), true);
                        m.assigned.ushr(operand);
                        m.constrained.ushr(operand);
                        m.increment = new Interval();
                        result.put(l, m);
                    }
                }
            }
            break;
        case Constants.ISHR:
            {
                Interval operand = new Interval();
                for (Location l : in.keySet()) {
                    if (l.stackLoc == context.stackPtr - 1) {
                        operand = in.get(l).assigned;
                    }
                }
                for (Location l : in.keySet()) {
                    if (l.stackLoc < context.stackPtr - 2) {
                        result.put(l, in.get(l));
                    } else if (l.stackLoc == context.stackPtr - 2) {
                        ValueMapping m = new ValueMapping(in.get(l), true);
                        m.assigned.shr(operand);
                        m.constrained.shr(operand);
                        m.increment = new Interval();
                        result.put(l, m);
                    }
                }
            }
            break;
        case Constants.IMUL:
            {
                Interval operand = new Interval();
                for (Location l : in.keySet()) {
                    if (l.stackLoc == context.stackPtr - 1) {
                        operand = in.get(l).assigned;
                    }
                }
                for (Location l : in.keySet()) {
                    if (l.stackLoc < context.stackPtr - 2) {
                        result.put(l, in.get(l));
                    } else if (l.stackLoc == context.stackPtr - 2) {
                        ValueMapping m = new ValueMapping(in.get(l), true);
                        m.assigned.mul(operand);
                        m.constrained.mul(operand);
                        m.increment = new Interval();
                        result.put(l, m);
                    }
                }
            }
            break;
        case Constants.IDIV:
            {
                Interval operand = new Interval();
                for (Location l : in.keySet()) {
                    if (l.stackLoc == context.stackPtr - 1) {
                        operand = in.get(l).assigned;
                    }
                }
                for (Location l : in.keySet()) {
                    if (l.stackLoc < context.stackPtr - 2) {
                        result.put(l, in.get(l));
                    } else if (l.stackLoc == context.stackPtr - 2) {
                        ValueMapping m = new ValueMapping(in.get(l), true);
                        m.assigned.div(operand);
                        m.constrained.div(operand);
                        m.increment = new Interval();
                        result.put(l, m);
                    }
                }
            }
            break;
        case Constants.IAND:
        case Constants.IOR:
        case Constants.IXOR:
        case Constants.IREM:
        case Constants.ISHL:
            {
                // TODO: we could be more clever for some operations
                for (Location l : in.keySet()) {
                    if (l.stackLoc < context.stackPtr - 2) {
                        result.put(l, in.get(l));
                    } else if (l.stackLoc == context.stackPtr - 2) {
                        ValueMapping m = new ValueMapping();
                        result.put(l, m);
                    }
                }
            }
            break;
        case Constants.I2B:
        case Constants.I2C:
        case Constants.I2S:
            // TODO: is this really correct?
            result = in;
            retval.put(context.callString, result);
            break;
        case Constants.MONITORENTER:
            result = in;
            retval.put(context.callString, result);
            context.syncLevel++;
            break;
        case Constants.MONITOREXIT:
            result = in;
            retval.put(context.callString, result);
            context.syncLevel--;
            if (context.syncLevel < 0) {
                System.err.println("Synchronization level mismatch.");
                System.exit(-1);
            }
            break;
        case Constants.CHECKCAST:
            result = in;
            retval.put(context.callString, result);
            break;
        case Constants.INSTANCEOF:
            {
                filterSet(in, result, context.stackPtr - 1);
                ValueMapping bool = new ValueMapping();
                bool.assigned.setLb(0);
                bool.assigned.setUb(1);
                result.put(new Location(context.stackPtr - 1), bool);
            }
            break;
        case Constants.NEW:
            {
                result = in;
                retval.put(context.callString, result);
            }
            break;
        case Constants.NEWARRAY:
            {
                NEWARRAY instr = (NEWARRAY) instruction;
                String name = instr.getType().toString();
                name += "@" + context.method() + ":" + stmt.getPosition();
                filterSet(in, result, context.stackPtr - 1);
                boolean valid = false;
                for (Location l : in.keySet()) {
                    if (l.stackLoc == context.stackPtr - 1) {
                        result.put(new Location(name + ".length"), in.get(l));
                        recordSize(stmt, context, in.get(l).assigned);
                        valid = true;
                    }
                }
                if (!valid) {
                    ValueMapping v = new ValueMapping();
                    result.put(new Location(name + ".length"), v);
                    recordSize(stmt, context, v.assigned);
                }
            }
            break;
        case Constants.ANEWARRAY:
            {
                ANEWARRAY instr = (ANEWARRAY) instruction;
                String name = instr.getType(context.constPool()).toString() + "[]";
                name += "@" + context.method() + ":" + stmt.getPosition();
                //System.out.println("NEW ARRAY: "+name);
                filterSet(in, result, context.stackPtr - 1);
                boolean valid = false;
                for (Location l : in.keySet()) {
                    if (l.stackLoc == context.stackPtr - 1) {
                        result.put(new Location(name + ".length"), in.get(l));
                        recordSize(stmt, context, in.get(l).assigned);
                        valid = true;
                    }
                }
                if (!valid) {
                    ValueMapping v = new ValueMapping();
                    result.put(new Location(name + ".length"), v);
                    recordSize(stmt, context, v.assigned);
                }
            }
            break;
        case Constants.MULTIANEWARRAY:
            {
                MULTIANEWARRAY instr = (MULTIANEWARRAY) instruction;
                int dim = instr.getDimensions();
                filterSet(in, result, context.stackPtr - dim);
                String type = instr.getType(context.constPool()).toString();
                type = type.substring(0, type.indexOf("["));
                Interval[] size = new Interval[dim];
                for (int i = 1; i <= dim; i++) {
                    String name = type;
                    for (int k = 0; k < i; k++) {
                        name += "[]";
                    }
                    name += "@" + context.method() + ":" + stmt.getPosition();
                    boolean valid = false;
                    for (Location l : in.keySet()) {
                        if (l.stackLoc == context.stackPtr - i) {
                            result.put(new Location(name + ".length"), in.get(l));
                            if (size[i - 1] != null) {
                                size[i - 1].join(in.get(l).assigned);
                            } else {
                                size[i - 1] = in.get(l).assigned;
                            }
                            valid = true;
                        }
                    }
                    if (!valid) {
                        ValueMapping v = new ValueMapping();
                        result.put(new Location(name + ".length"), v);
                        size[i - 1] = v.assigned;
                    }
                }
                recordSize(stmt, context, size);
            }
            break;
        case Constants.GOTO:
            result = in;
            retval.put(context.callString, result);
            break;
        case Constants.IFNULL:
        case Constants.IFNONNULL:
            {
                checkScope(context, stmt);
                filterSet(in, result, context.stackPtr - 1);
            }
            break;
        case Constants.IF_ACMPEQ:
        case Constants.IF_ACMPNE:
            {
                checkScope(context, stmt);
                filterSet(in, result, context.stackPtr - 2);
            }
            break;
        case Constants.IFEQ:
        case Constants.IFNE:
        case Constants.IFLT:
        case Constants.IFGE:
        case Constants.IFLE:
        case Constants.IFGT:
            checkScope(context, stmt);
            result = doIf(stmt, edge, context, in, result);
            retval.put(context.callString, result);
            break;
        case Constants.IF_ICMPEQ:
        case Constants.IF_ICMPNE:
        case Constants.IF_ICMPLT:
        case Constants.IF_ICMPGE:
        case Constants.IF_ICMPGT:
        case Constants.IF_ICMPLE:
            checkScope(context, stmt);
            result = doIfIcmp(stmt, edge, context, in, result);
            retval.put(context.callString, result);
            break;
        case Constants.LOOKUPSWITCH:
        case Constants.TABLESWITCH:
            result = in;
            retval.put(context.callString, result);
            break;
        case Constants.INVOKEVIRTUAL:
        case Constants.INVOKEINTERFACE:
        case Constants.INVOKESTATIC:
        case Constants.INVOKESPECIAL:
            {
                DFATool p = interpreter.getDFATool();
                Set<String> receivers = p.getReceivers(stmt, context.callString);
                if (receivers == null) {
                    warnUnknownReceivers(context, stmt);
                    result = in;
                    break;
                }
                for (String methodName : receivers) {
                    doInvoke(methodName, stmt, context, input, interpreter, state, retval);
                }
            }
            break;
        case Constants.ARETURN:
        case Constants.RETURN:
            {
                filterSet(in, result, 0);
            }
            break;
        case Constants.IRETURN:
            {
                filterSet(in, result, 0);
                for (Location l : in.keySet()) {
                    if (l.stackLoc == context.stackPtr - 1) {
                        result.put(new Location(0), new ValueMapping(in.get(l), false));
                    }
                }
            }
            break;
        default:
            //			System.out.println("unknown instruction: "+stmt);
            result = in;
            retval.put(context.callString, result);
            break;
    }
    //		System.out.println(stmt);
    //		System.out.print(stmt.getInstruction()+":\t{ ");
    //		if (retval != null) {
    //			for (Iterator<Map<Location, ValueMapping>> k = retval.values().iterator(); k.hasNext(); ) {
    //				Map<Location, ValueMapping> m = k.next();
    //				System.out.print(m+", ");
    //			}
    //		}
    //		System.out.println("}");
    context.stackPtr += instruction.produceStack(context.constPool()) - instruction.consumeStack(context.constPool());
    return retval;
}
Also used : Set(java.util.Set) LinkedHashSet(java.util.LinkedHashSet) MULTIANEWARRAY(org.apache.bcel.generic.MULTIANEWARRAY) ANEWARRAY(org.apache.bcel.generic.ANEWARRAY) LDC(org.apache.bcel.generic.LDC) CallString(com.jopdesign.common.code.CallString) LoadInstruction(org.apache.bcel.generic.LoadInstruction) StoreInstruction(org.apache.bcel.generic.StoreInstruction) Instruction(org.apache.bcel.generic.Instruction) ConstantPushInstruction(org.apache.bcel.generic.ConstantPushInstruction) BranchInstruction(org.apache.bcel.generic.BranchInstruction) ReferenceType(org.apache.bcel.generic.ReferenceType) LinkedHashMap(java.util.LinkedHashMap) PUTSTATIC(org.apache.bcel.generic.PUTSTATIC) LoadInstruction(org.apache.bcel.generic.LoadInstruction) Context(com.jopdesign.dfa.framework.Context) MULTIANEWARRAY(org.apache.bcel.generic.MULTIANEWARRAY) ANEWARRAY(org.apache.bcel.generic.ANEWARRAY) NEWARRAY(org.apache.bcel.generic.NEWARRAY) DFATool(com.jopdesign.dfa.DFATool) PUTFIELD(org.apache.bcel.generic.PUTFIELD) MULTIANEWARRAY(org.apache.bcel.generic.MULTIANEWARRAY) ContextMap(com.jopdesign.dfa.framework.ContextMap) CallString(com.jopdesign.common.code.CallString) GETFIELD(org.apache.bcel.generic.GETFIELD) ReferenceType(org.apache.bcel.generic.ReferenceType) Type(org.apache.bcel.generic.Type) IINC(org.apache.bcel.generic.IINC) ConstantPushInstruction(org.apache.bcel.generic.ConstantPushInstruction) GETSTATIC(org.apache.bcel.generic.GETSTATIC) Map(java.util.Map) LinkedHashMap(java.util.LinkedHashMap) ContextMap(com.jopdesign.dfa.framework.ContextMap) StoreInstruction(org.apache.bcel.generic.StoreInstruction)

Example 2 with DFATool

use of com.jopdesign.dfa.DFATool in project jop by jop-devel.

the class SymbolicPointsTo method doInvoke.

private void doInvoke(String methodName, InstructionHandle stmt, Context context, ContextMap<CallString, SymbolicAddressMap> input, Interpreter<CallString, SymbolicAddressMap> interpreter, Map<InstructionHandle, ContextMap<CallString, SymbolicAddressMap>> state, ContextMap<CallString, SymbolicAddressMap> retval) {
    DFATool p = interpreter.getDFATool();
    MethodInfo method = p.getMethod(methodName);
    if (method.isNative()) {
        handleNative(method, context, input, retval);
    } else {
        // set up new context
        int varPtr = context.stackPtr - MethodHelper.getArgSize(method);
        Context c = new Context(context);
        c.stackPtr = method.getCode().getMaxLocals();
        if (method.isSynchronized()) {
            c.syncLevel = context.syncLevel + 1;
        }
        c.setMethodInfo(method);
        c.callString = c.callString.push(method, stmt, callStringLength);
        // carry only minimal information with call
        SymbolicAddressMap in = input.get(context.callString);
        SymbolicAddressMap out = in.cloneInvoke(varPtr);
        HashMap<CallString, SymbolicAddressMap> initialMap = new HashMap<CallString, SymbolicAddressMap>();
        ContextMap<CallString, SymbolicAddressMap> tmpresult = new ContextMap<CallString, SymbolicAddressMap>(c, initialMap);
        tmpresult.put(c.callString, out);
        InstructionHandle entry = p.getEntryHandle(method);
        state.put(entry, join(state.get(entry), tmpresult));
        if (DEBUG_PRINT) {
            System.out.println("[I] Invoke: " + method.getMemberID());
            System.out.println(String.format("  StackPtr: %d, framePtr: %d, args: %d", context.stackPtr, varPtr, MethodHelper.getArgSize(method)));
        }
        // interpret method
        Map<InstructionHandle, ContextMap<CallString, SymbolicAddressMap>> r = interpreter.interpret(c, entry, state, false);
        SymbolicAddressMap ctxInfo = retval.get(context.callString);
        // pull out relevant information from call
        InstructionHandle exit = p.getExitHandle(method);
        if (r.get(exit) != null) {
            SymbolicAddressMap returned = r.get(exit).get(c.callString);
            if (returned != null) {
                ctxInfo.joinReturned(returned, varPtr);
            } else {
                System.err.println("doInvoke(): No exit information for callstring ?");
            }
        } else {
            System.err.println("Symbolic Points To[doInvoke()]: No exit information from " + methodName + "?");
        }
        // add relevant information to result
        ctxInfo.addStackUpto(in, context.stackPtr - MethodHelper.getArgSize(method));
        if (DEBUG_PRINT) {
            System.out.println("[R] Invoke: " + method.getMemberID());
            System.out.println(String.format("  StackPtr: %d, framePtr: %d, args: %d", context.stackPtr, varPtr, MethodHelper.getArgSize(method)));
        }
    }
}
Also used : Context(com.jopdesign.dfa.framework.Context) DFATool(com.jopdesign.dfa.DFATool) HashMap(java.util.HashMap) MethodInfo(com.jopdesign.common.MethodInfo) ContextMap(com.jopdesign.dfa.framework.ContextMap) InstructionHandle(org.apache.bcel.generic.InstructionHandle) CallString(com.jopdesign.common.code.CallString)

Example 3 with DFATool

use of com.jopdesign.dfa.DFATool in project jop by jop-devel.

the class SymbolicPointsTo method transfer.

public ContextMap<CallString, SymbolicAddressMap> transfer(InstructionHandle stmt, FlowEdge edge, ContextMap<CallString, SymbolicAddressMap> input, Interpreter<CallString, SymbolicAddressMap> interpreter, Map<InstructionHandle, ContextMap<CallString, SymbolicAddressMap>> state) {
    Context context = new Context(input.getContext());
    if (DEBUG_PRINT) {
        System.out.println("[S] " + context.callString.toStringList() + ": " + context.method() + " / " + stmt);
    }
    SymbolicAddressMap in = input.get(context.callString);
    ContextMap<CallString, SymbolicAddressMap> retval = new ContextMap<CallString, SymbolicAddressMap>(context, input);
    Instruction instruction = stmt.getInstruction();
    int newStackPtr = context.stackPtr + instruction.produceStack(context.constPool()) - instruction.consumeStack(context.constPool());
    int opcode = instruction.getOpcode();
    switch(opcode) {
        /* Constants (boring) */
        case Constants.DCONST_0:
        case Constants.DCONST_1:
        case Constants.LCONST_0:
        case Constants.LCONST_1:
        /* Instructions above need two stack slots */
        case Constants.FCONST_0:
        case Constants.FCONST_1:
        case Constants.FCONST_2:
        case Constants.ICONST_M1:
        case Constants.ICONST_0:
        case Constants.ICONST_1:
        case Constants.ICONST_2:
        case Constants.ICONST_3:
        case Constants.ICONST_4:
        case Constants.ICONST_5:
        case Constants.BIPUSH:
        case Constants.SIPUSH:
            {
                retval.put(context.callString, in.cloneFilterStack(newStackPtr));
            }
            break;
        case Constants.ACONST_NULL:
            {
                // Null -> No reference
                SymbolicAddressMap result = in.cloneFilterStack(newStackPtr);
                result.putStack(newStackPtr - 1, bsFactory.empty());
                retval.put(context.callString, result);
            }
            break;
        /* Long/Double Constants */
        case Constants.LDC2_W:
            {
                retval.put(context.callString, in.cloneFilterStack(newStackPtr));
            }
            break;
        /* Int/Float/String Constants */
        case Constants.LDC:
        case Constants.LDC_W:
            {
                LDC ldc = (LDC) instruction;
                Type t = ldc.getType(context.constPool());
                if (t instanceof ReferenceType) {
                    SymbolicAddressMap result = in.cloneFilterStack(newStackPtr);
                    /* FIXME: This is overly conservative, but class pointer not available here */
                    String classContext = context.getMethodInfo().getMemberID().toString();
                    SymbolicAddress addr = SymbolicAddress.stringLiteral(classContext, ldc.getIndex());
                    result.putStack(newStackPtr - 1, bsFactory.singleton(addr));
                    retval.put(context.callString, result);
                } else {
                    retval.put(context.callString, in.cloneFilterStack(newStackPtr));
                }
            }
            break;
        case Constants.DSTORE:
        case Constants.DSTORE_0:
        case Constants.DSTORE_1:
        case Constants.DSTORE_2:
        case Constants.DSTORE_3:
        case Constants.LSTORE:
        case Constants.LSTORE_0:
        case Constants.LSTORE_1:
        case Constants.LSTORE_2:
        case Constants.LSTORE_3:
        case Constants.FSTORE:
        case Constants.FSTORE_0:
        case Constants.FSTORE_1:
        case Constants.FSTORE_2:
        case Constants.FSTORE_3:
        case Constants.ISTORE_0:
        case Constants.ISTORE_1:
        case Constants.ISTORE_2:
        case Constants.ISTORE_3:
        case Constants.ISTORE:
            {
                retval.put(context.callString, in.cloneFilterStack(newStackPtr));
            }
            break;
        // 
        case Constants.ASTORE_0:
        case Constants.ASTORE_1:
        case Constants.ASTORE_2:
        case Constants.ASTORE_3:
        case Constants.ASTORE:
            {
                // copy value to local variable
                StoreInstruction instr = (StoreInstruction) instruction;
                SymbolicAddressMap result = in.cloneFilterStack(newStackPtr);
                if (DEBUG_PRINT) {
                    System.out.println(String.format("[DD] Copy: stack[%d] <- stack[%d]", instr.getIndex(), context.stackPtr - 1));
                }
                result.copyStack(in, instr.getIndex(), context.stackPtr - 1);
                retval.put(context.callString, result);
            }
            break;
        /* Load variables (boring) */
        case Constants.DLOAD_0:
        case Constants.DLOAD_1:
        case Constants.DLOAD_2:
        case Constants.DLOAD_3:
        case Constants.DLOAD:
        case Constants.LLOAD_0:
        case Constants.LLOAD_1:
        case Constants.LLOAD_2:
        case Constants.LLOAD_3:
        case Constants.LLOAD:
        /* Instructions above need two stack slots */
        case Constants.FLOAD_0:
        case Constants.FLOAD_1:
        case Constants.FLOAD_2:
        case Constants.FLOAD_3:
        case Constants.FLOAD:
        case Constants.ILOAD_0:
        case Constants.ILOAD_1:
        case Constants.ILOAD_2:
        case Constants.ILOAD_3:
        case Constants.ILOAD:
            {
                retval.put(context.callString, in.cloneFilterStack(newStackPtr));
            }
            break;
        /* Floating Point Comparison (boring) */
        case Constants.DCMPG:
        case Constants.DCMPL:
        case Constants.LCMP:
        /* Instructions above need two stack slots */
        case Constants.FCMPG:
        case Constants.FCMPL:
            {
                retval.put(context.callString, in.cloneFilterStack(newStackPtr));
            }
            break;
        case Constants.ALOAD_0:
        case Constants.ALOAD_1:
        case Constants.ALOAD_2:
        case Constants.ALOAD_3:
        case Constants.ALOAD:
            {
                LoadInstruction instr = (LoadInstruction) instruction;
                // copy value from local variable
                SymbolicAddressMap result = in.cloneFilterStack(newStackPtr);
                result.copyStack(in, context.stackPtr, instr.getIndex());
                retval.put(context.callString, result);
            }
            break;
        // Access Object Handle (area), top of stack
        case Constants.ARRAYLENGTH:
            {
                putResult(stmt, context, input.get(context.callString).getStack(context.stackPtr - 1));
                retval.put(context.callString, in.cloneFilterStack(newStackPtr));
            }
            break;
        // Access Object Handle, second on stack
        case Constants.PUTFIELD:
            {
                PUTFIELD instr = (PUTFIELD) instruction;
                putResult(stmt, context, input.get(context.callString).getStack(context.stackPtr - 1 - instr.getType(context.constPool()).getSize()));
                SymbolicAddressMap result = in.cloneFilterStack(newStackPtr);
                // Change alias information
                if (instr.getFieldType(context.constPool()) instanceof ReferenceType) {
                    String ty = instr.getFieldType(context.constPool()).getSignature();
                    result.addAlias(ty, in.getStack(context.stackPtr - 1));
                }
                retval.put(context.callString, result);
            }
            break;
        // Access Object Handle, top of stack
        case Constants.GETFIELD:
            {
                putResult(stmt, context, input.get(context.callString).getStack(context.stackPtr - 1));
                GETFIELD instr = (GETFIELD) instruction;
                SymbolicAddressMap result = in.cloneFilterStack(newStackPtr);
                if (instr.getFieldType(context.constPool()) instanceof ReferenceType) {
                    BoundedSet<SymbolicAddress> newMapping = SymbolicAddress.fieldAccess(bsFactory, in.getStack(context.stackPtr - 1), instr.getFieldName(context.constPool()));
                    newMapping.addAll(in.getAliases(instr.getFieldType(context.constPool()).getSignature()));
                    result.putStack(context.stackPtr - 1, newMapping);
                }
                retval.put(context.callString, result);
            }
            break;
        // Handles the same way as MOV
        case Constants.PUTSTATIC:
            {
                PUTSTATIC instr = (PUTSTATIC) instruction;
                SymbolicAddressMap result = in.cloneFilterStack(newStackPtr);
                if (instr.getFieldType(context.constPool()) instanceof ReferenceType) {
                    BoundedSet<SymbolicAddress> pointers = in.getStack(context.stackPtr - 1);
                    result.putHeap(fieldSignature(context, instr), pointers);
                }
                retval.put(context.callString, result);
            }
            break;
        // Handled the same as MOV
        case Constants.GETSTATIC:
            {
                GETSTATIC instr = (GETSTATIC) instruction;
                SymbolicAddressMap result = in.cloneFilterStack(newStackPtr);
                if (instr.getFieldType(context.constPool()) instanceof ReferenceType) {
                    result.putStack(context.stackPtr, in.getHeap(fieldSignature(context, instr)));
                }
                retval.put(context.callString, result);
            }
            break;
        case Constants.LASTORE:
        case Constants.DASTORE:
        case Constants.IASTORE:
        case Constants.FASTORE:
        case Constants.CASTORE:
        case Constants.SASTORE:
        case Constants.BASTORE:
            {
                int offset = 3;
                if (opcode == Constants.LASTORE || opcode == Constants.DASTORE)
                    offset = 4;
                putResult(stmt, context, input.get(context.callString).getStack(context.stackPtr - offset));
                retval.put(context.callString, in.cloneFilterStack(newStackPtr));
            }
            break;
        // changing the heap -> TOP
        case Constants.AASTORE:
            {
                putResult(stmt, context, input.get(context.callString).getStack(context.stackPtr - 3));
                AASTORE instr = (AASTORE) stmt.getInstruction();
                SymbolicAddressMap result = in.cloneFilterStack(newStackPtr);
                // Change alias information
                if (instr.getType(context.constPool()) instanceof ReferenceType) {
                    String ty = instr.getType(context.constPool()).getSignature();
                    result.addAlias(ty, in.getStack(context.stackPtr - 1));
                }
                retval.put(context.callString, result);
            }
            break;
        case Constants.DALOAD:
        case Constants.LALOAD:
        case Constants.IALOAD:
        case Constants.FALOAD:
        case Constants.CALOAD:
        case Constants.SALOAD:
        case Constants.BALOAD:
            {
                putResult(stmt, context, input.get(context.callString).getStack(context.stackPtr - 2));
                retval.put(context.callString, in.cloneFilterStack(newStackPtr));
            }
            break;
        // TODO: Use index info
        case Constants.AALOAD:
            {
                putResult(stmt, context, input.get(context.callString).getStack(context.stackPtr - 2));
                //AALOAD instr = (AALOAD)instruction;
                SymbolicAddressMap result = in.cloneFilterStack(newStackPtr);
                BoundedSet<SymbolicAddress> objectMapping = in.getStack(context.stackPtr - 2);
                BoundedSet<SymbolicAddress> newMapping;
                LoopBounds bounds = interpreter.getDFATool().getLoopBounds();
                if (executedOnce.query(stmt)) {
                    newMapping = bsFactory.singleton(SymbolicAddress.newName());
                } else if (objectMapping.isSaturated() || bounds == null) {
                    newMapping = bsFactory.top();
                } else {
                    Interval interval = bounds.getArrayIndices(stmt, context.callString);
                    if (interval.hasLb() && interval.hasUb()) {
                        newMapping = bsFactory.empty();
                        for (SymbolicAddress addr : objectMapping.getSet()) {
                            for (int i = interval.getLb(); i <= interval.getUb(); i++) {
                                newMapping.add(addr.accessArray(i));
                            }
                        }
                    } else {
                        newMapping = bsFactory.top();
                    }
                }
                //				Doesn't work, but is probably stupid anyway :(
                //  			LoopBounds bounds = interpreter.getDFATool().getLoopBounds();
                //              bounds.getArraySizes().get(stmt).get(context.callString);
                //			    newMapping = bsFactory.empty();
                //				Interval[] sizeBounds = { new Interval(2,3) }; 
                //				for(Interval i : sizeBounds) {
                //					if(! i.hasUb()) {
                //						newMapping = bsFactory.top();
                //					}
                //					int ub = i.getUb();
                //					for(int j = 0; j <= ub; j++) {
                //						for(SymbolicAddress addr: objectMapping.getSet()) {
                //							newMapping.add(addr.accessArray(j));
                //						}					
                //					}
                //				}
                //			}
                result.putStack(context.stackPtr - 2, newMapping);
                retval.put(context.callString, result);
            }
            break;
        case Constants.DUP:
            {
                // copy value on stack
                SymbolicAddressMap result = in.cloneFilterStack(newStackPtr);
                result.copyStack(in, context.stackPtr, context.stackPtr - 1);
                retval.put(context.callString, result);
            }
            break;
        case Constants.DUP_X1:
            {
                // copy value on stack
                SymbolicAddressMap result = in.cloneFilterStack(context.stackPtr - 2);
                result.copyStack(in, context.stackPtr - 2, context.stackPtr - 1);
                result.copyStack(in, context.stackPtr - 1, context.stackPtr - 2);
                result.copyStack(in, context.stackPtr, context.stackPtr - 1);
                retval.put(context.callString, result);
            }
            break;
        case Constants.DUP_X2:
            {
                // copy value on stack
                SymbolicAddressMap result = in.cloneFilterStack(context.stackPtr - 3);
                result.copyStack(in, context.stackPtr - 3, context.stackPtr - 1);
                result.copyStack(in, context.stackPtr - 2, context.stackPtr - 3);
                result.copyStack(in, context.stackPtr - 1, context.stackPtr - 2);
                result.copyStack(in, context.stackPtr, context.stackPtr - 1);
                retval.put(context.callString, result);
            }
            break;
        case Constants.DUP2:
            {
                // v1,v2 -> v1,v2,v1,v2
                SymbolicAddressMap result = in.cloneFilterStack(context.stackPtr);
                result.copyStack(in, context.stackPtr, context.stackPtr - 2);
                result.copyStack(in, context.stackPtr + 1, context.stackPtr - 1);
                retval.put(context.callString, result);
            }
            break;
        case Constants.POP:
        case Constants.POP2:
            {
                retval.put(context.callString, in.cloneFilterStack(newStackPtr));
            }
            break;
        case Constants.IINC:
            {
                retval.put(context.callString, in.cloneFilterStack(newStackPtr));
            }
            break;
        case Constants.IADD:
        case Constants.ISUB:
        case Constants.INEG:
        case Constants.IUSHR:
        case Constants.ISHR:
        case Constants.IAND:
        case Constants.IOR:
        case Constants.IXOR:
        case Constants.IMUL:
        case Constants.IDIV:
        case Constants.IREM:
        case Constants.ISHL:
            {
                retval.put(context.callString, in.cloneFilterStack(newStackPtr));
            }
            break;
        /* Long,Float and Double operations (boring) */
        case Constants.DADD:
        case Constants.DSUB:
        case Constants.DMUL:
        case Constants.DDIV:
        case Constants.DREM:
        case Constants.LADD:
        case Constants.LSUB:
        case Constants.LUSHR:
        case Constants.LSHR:
        case Constants.LAND:
        case Constants.LOR:
        case Constants.LXOR:
        case Constants.LMUL:
        case Constants.LDIV:
        case Constants.LREM:
        case Constants.LSHL:
        /* Instructions above need two stack slots */
        case Constants.DNEG:
        case Constants.LNEG:
        case Constants.FADD:
        case Constants.FSUB:
        case Constants.FNEG:
        case Constants.FMUL:
        case Constants.FDIV:
        case Constants.FREM:
            {
                retval.put(context.callString, in.cloneFilterStack(newStackPtr));
            }
            break;
        /* Conversion of primitives (boring) */
        case Constants.D2F:
        case Constants.D2I:
        /* Instructions above need two stack slots */
        case Constants.D2L:
            {
                retval.put(context.callString, in.cloneFilterStack(newStackPtr));
            }
            break;
        case Constants.L2F:
        case Constants.L2I:
        /* Instructions above need two stack slots */
        case Constants.L2D:
            {
                retval.put(context.callString, in.cloneFilterStack(newStackPtr));
            }
            break;
        case Constants.F2D:
        case Constants.I2D:
        case Constants.F2L:
        case Constants.I2L:
        /* Instructions above need one stack slot less */
        case Constants.F2I:
        case Constants.I2B:
        case Constants.I2C:
        case Constants.I2F:
        case Constants.I2S:
            {
                retval.put(context.callString, in.cloneFilterStack(newStackPtr));
            }
            break;
        case Constants.MONITORENTER:
            // not supported yet
            if (ASSUME_NO_CONC)
                retval.put(context.callString, in.cloneFilterStack(newStackPtr));
            else
                retval.put(context.callString, SymbolicAddressMap.top());
            break;
        case Constants.MONITOREXIT:
            // not supported yet
            retval.put(context.callString, in.cloneFilterStack(newStackPtr));
            break;
        case Constants.CHECKCAST:
            retval.put(context.callString, in.cloneFilterStack(newStackPtr));
            break;
        case Constants.INSTANCEOF:
            {
                retval.put(context.callString, in.cloneFilterStack(newStackPtr));
            }
            break;
        case Constants.NEW:
        case Constants.NEWARRAY:
        case Constants.ANEWARRAY:
            {
                SymbolicAddressMap result = in.cloneFilterStack(newStackPtr);
                BoundedSet<SymbolicAddress> newMapping;
                if (executedOnce.query(stmt)) {
                    newMapping = bsFactory.singleton(SymbolicAddress.newName());
                } else {
                    newMapping = bsFactory.top();
                }
                int objPtr = (instruction.getOpcode() == Constants.NEW) ? context.stackPtr : (context.stackPtr - 1);
                result.putStack(objPtr, newMapping);
                retval.put(context.callString, result);
            }
            break;
        case Constants.MULTIANEWARRAY:
            {
                // not supported yet
                retval.put(context.callString, SymbolicAddressMap.top());
            }
            break;
        case Constants.GOTO:
            retval.put(context.callString, in.cloneFilterStack(newStackPtr));
            break;
        case Constants.IFNULL:
        case Constants.IFNONNULL:
            {
                retval.put(context.callString, in.cloneFilterStack(newStackPtr));
            }
            break;
        case Constants.IF_ACMPEQ:
        case Constants.IF_ACMPNE:
            {
                retval.put(context.callString, in.cloneFilterStack(newStackPtr));
            }
            break;
        case Constants.IFEQ:
        case Constants.IFNE:
        case Constants.IFLT:
        case Constants.IFGE:
        case Constants.IFLE:
        case Constants.IFGT:
            retval.put(context.callString, in.cloneFilterStack(newStackPtr));
            break;
        case Constants.IF_ICMPEQ:
        case Constants.IF_ICMPNE:
        case Constants.IF_ICMPLT:
        case Constants.IF_ICMPGE:
        case Constants.IF_ICMPGT:
        case Constants.IF_ICMPLE:
            retval.put(context.callString, in.cloneFilterStack(newStackPtr));
            break;
        case Constants.LOOKUPSWITCH:
        case Constants.TABLESWITCH:
            retval.put(context.callString, in.cloneFilterStack(newStackPtr));
            break;
        case Constants.INVOKEVIRTUAL:
        case Constants.INVOKEINTERFACE:
        case Constants.INVOKESTATIC:
        case Constants.INVOKESPECIAL:
            {
                DFATool p = interpreter.getDFATool();
                Set<String> receivers = p.getReceivers(stmt, context.callString);
                retval.put(context.callString, new SymbolicAddressMap(bsFactory));
                if (receivers == null || receivers.size() == 0) {
                    String errMsg = String.format("%s : invoke %s: %s receivers", context.method(), instruction.toString(context.constPool().getConstantPool()), (receivers == null ? "Unknown" : "No"));
                    // Get static receivers (FIXME: this just workarounds DFA bugs)
                    if (opcode == Constants.INVOKESTATIC) {
                        receivers = new HashSet<String>();
                        InvokeInstruction invInstruction = (InvokeInstruction) instruction;
                        String klass = invInstruction.getClassName(context.constPool());
                        String name = invInstruction.getMethodName(context.constPool());
                        String sig = invInstruction.getSignature(context.constPool());
                        String recv = klass + "." + name + sig;
                        Logger.getLogger(this.getClass()).info("Using static receiver: " + recv);
                        receivers.add(recv);
                    } else {
                        Logger.getLogger(this.getClass()).error(errMsg);
                        throw new AssertionError(errMsg);
                    }
                }
                if (instruction.getOpcode() == Constants.INVOKEVIRTUAL || instruction.getOpcode() == Constants.INVOKEINTERFACE) {
                    MethodInfo mi = p.getMethod(receivers.iterator().next());
                    int refPos = MethodHelper.getArgSize(mi);
                    //						mi.methodId,refPos,context.stackPtr,input.get(context.callString)));
                    try {
                        putResult(stmt, context, input.get(context.callString).getStack(context.stackPtr - refPos));
                    } catch (Error e) {
                        System.err.println("We have problems with method " + mi);
                        System.err.println(e.getMessage());
                    }
                }
                for (String methodName : receivers) {
                    doInvoke(methodName, stmt, context, input, interpreter, state, retval);
                }
            }
            break;
        case Constants.ARETURN:
            {
                SymbolicAddressMap result = in.cloneFilterStack(0);
                // store results
                result.copyStack(in, 0, context.stackPtr - 1);
                retval.put(context.callString, result);
            }
            break;
        /* The values of other return statements are not of interest here */
        case Constants.DRETURN:
        case Constants.LRETURN:
        case Constants.FRETURN:
        case Constants.IRETURN:
        case Constants.RETURN:
            {
                retval.put(context.callString, in.cloneFilterStack(newStackPtr));
            }
            break;
        default:
            System.err.println("unknown instruction: " + stmt + " in method " + context.method());
            retval.put(context.callString, in.cloneFilterStack(newStackPtr));
            break;
    }
    // DEBUGGING
    if (DEBUG_PRINT) {
        System.out.println("[F] " + context.method() + " / " + stmt);
        System.out.println("  Stackptr: " + context.stackPtr + " -> " + newStackPtr);
        System.out.println("  Before: ");
        input.get(context.callString).print(System.out, 4);
        System.out.println("  After: ");
        retval.get(context.callString).print(System.out, 4);
    }
    context.stackPtr = newStackPtr;
    return retval;
}
Also used : HashSet(java.util.HashSet) Set(java.util.Set) BoundedSet(com.jopdesign.dfa.framework.BoundedSetFactory.BoundedSet) LDC(org.apache.bcel.generic.LDC) CallString(com.jopdesign.common.code.CallString) InvokeInstruction(org.apache.bcel.generic.InvokeInstruction) ArrayInstruction(org.apache.bcel.generic.ArrayInstruction) LoadInstruction(org.apache.bcel.generic.LoadInstruction) StoreInstruction(org.apache.bcel.generic.StoreInstruction) Instruction(org.apache.bcel.generic.Instruction) FieldInstruction(org.apache.bcel.generic.FieldInstruction) ReferenceType(org.apache.bcel.generic.ReferenceType) PUTSTATIC(org.apache.bcel.generic.PUTSTATIC) LoadInstruction(org.apache.bcel.generic.LoadInstruction) HashSet(java.util.HashSet) Context(com.jopdesign.dfa.framework.Context) DFATool(com.jopdesign.dfa.DFATool) PUTFIELD(org.apache.bcel.generic.PUTFIELD) AppInfoError(com.jopdesign.common.misc.AppInfoError) ContextMap(com.jopdesign.dfa.framework.ContextMap) CallString(com.jopdesign.common.code.CallString) GETFIELD(org.apache.bcel.generic.GETFIELD) BoundedSet(com.jopdesign.dfa.framework.BoundedSetFactory.BoundedSet) InvokeInstruction(org.apache.bcel.generic.InvokeInstruction) ReferenceType(org.apache.bcel.generic.ReferenceType) Type(org.apache.bcel.generic.Type) AASTORE(org.apache.bcel.generic.AASTORE) MethodInfo(com.jopdesign.common.MethodInfo) GETSTATIC(org.apache.bcel.generic.GETSTATIC) StoreInstruction(org.apache.bcel.generic.StoreInstruction)

Example 4 with DFATool

use of com.jopdesign.dfa.DFATool in project jop by jop-devel.

the class CallStringReceiverTypes method doInvokeStatic.

private void doInvokeStatic(String methodName, InstructionHandle stmt, Context context, ContextMap<CallString, Set<TypeMapping>> input, Interpreter<CallString, Set<TypeMapping>> interpreter, Map<InstructionHandle, ContextMap<CallString, Set<TypeMapping>>> state, ContextMap<CallString, Set<TypeMapping>> result) {
    DFATool p = interpreter.getDFATool();
    MethodInfo method = p.getMethod(methodName);
    if (method == null) {
        throw new AppInfoError("DFA: cannot find static method " + methodName);
    }
    //noinspection AssignmentToMethodParameter
    methodName = method.getClassName() + "." + method.getMethodSignature();
    recordReceiver(stmt, context, methodName);
    if (method.isNative()) {
        handleNative(method, context, input, result);
    } else {
        // set up new context
        int varPtr = context.stackPtr - MethodHelper.getArgSize(method);
        Context c = new Context(context);
        c.stackPtr = method.getCode().getMaxLocals();
        if (method.isSynchronized()) {
            c.syncLevel = context.syncLevel + 1;
        }
        c.setMethodInfo(method);
        c.callString = c.callString.push(context.getMethodInfo(), stmt, callStringLength);
        // carry only minimal information with call
        Set<TypeMapping> in = input.get(context.callString);
        Set<TypeMapping> out = new LinkedHashSet<TypeMapping>();
        ContextMap<CallString, Set<TypeMapping>> tmpresult = new ContextMap<CallString, Set<TypeMapping>>(c, new LinkedHashMap<CallString, Set<TypeMapping>>());
        tmpresult.put(c.callString, out);
        for (TypeMapping m : in) {
            if (m.stackLoc < 0) {
                out.add(m);
            }
            if (m.stackLoc >= varPtr) {
                out.add(new TypeMapping(m.stackLoc - varPtr, m.type));
            }
        }
        InstructionHandle entry = p.getEntryHandle(method);
        state.put(entry, join(state.get(entry), tmpresult));
        // interpret method
        Map<InstructionHandle, ContextMap<CallString, Set<TypeMapping>>> r = interpreter.interpret(c, entry, state, false);
        // pull out relevant information from call
        InstructionHandle exit = p.getExitHandle(method);
        if (r.get(exit) != null) {
            Set<TypeMapping> returned = r.get(exit).get(c.callString);
            if (returned != null) {
                filterReturnSet(returned, result.get(context.callString), varPtr);
            }
        }
    }
}
Also used : Context(com.jopdesign.dfa.framework.Context) LinkedHashSet(java.util.LinkedHashSet) DFATool(com.jopdesign.dfa.DFATool) LinkedHashSet(java.util.LinkedHashSet) Set(java.util.Set) AppInfoError(com.jopdesign.common.misc.AppInfoError) ContextMap(com.jopdesign.dfa.framework.ContextMap) InstructionHandle(org.apache.bcel.generic.InstructionHandle) CallString(com.jopdesign.common.code.CallString) MethodInfo(com.jopdesign.common.MethodInfo)

Example 5 with DFATool

use of com.jopdesign.dfa.DFATool in project jop by jop-devel.

the class CallStringReceiverTypes method transfer.

public ContextMap<CallString, Set<TypeMapping>> transfer(InstructionHandle stmt, FlowEdge edge, ContextMap<CallString, Set<TypeMapping>> input, Interpreter<CallString, Set<TypeMapping>> interpreter, Map<InstructionHandle, ContextMap<CallString, Set<TypeMapping>>> state) {
    Context context = new Context(input.getContext());
    Set<TypeMapping> in = input.get(context.callString);
    ContextMap<CallString, Set<TypeMapping>> retval = new ContextMap<CallString, Set<TypeMapping>>(context, new LinkedHashMap<CallString, Set<TypeMapping>>());
    Set<TypeMapping> result = new LinkedHashSet<TypeMapping>();
    retval.put(context.callString, result);
    Instruction instruction = stmt.getInstruction();
    switch(instruction.getOpcode()) {
        case Constants.NOP:
            result = in;
            retval.put(context.callString, result);
            break;
        case Constants.ACONST_NULL:
        case Constants.ICONST_M1:
        case Constants.ICONST_0:
        case Constants.ICONST_1:
        case Constants.ICONST_2:
        case Constants.ICONST_3:
        case Constants.ICONST_4:
        case Constants.ICONST_5:
        case Constants.BIPUSH:
        case Constants.SIPUSH:
        case Constants.FCONST_0:
        case Constants.FCONST_1:
        case Constants.FCONST_2:
        case Constants.LCONST_0:
        case Constants.LCONST_1:
        case Constants.DCONST_0:
        case Constants.DCONST_1:
        case Constants.LDC2_W:
            result = in;
            retval.put(context.callString, result);
            break;
        case Constants.LDC:
        case Constants.LDC_W:
            {
                LDC instr = (LDC) instruction;
                result = new LinkedHashSet<TypeMapping>(in);
                retval.put(context.callString, result);
                Type type = instr.getType(context.constPool());
                if (type.equals(Type.STRING)) {
                    result.add(new TypeMapping(context.stackPtr, type.toString()));
                    String value = type.toString() + ".value";
                    String name = "char[]";
                    name += "@" + context.method() + ":" + stmt.getPosition();
                    result.add(new TypeMapping(value, name));
                }
            }
            break;
        case Constants.DUP:
            {
                for (TypeMapping m : in) {
                    result.add(m);
                    if (m.stackLoc == context.stackPtr - 1) {
                        result.add(new TypeMapping(context.stackPtr, m.type));
                    }
                }
            }
            break;
        case Constants.DUP_X1:
            {
                for (TypeMapping m : in) {
                    if (m.stackLoc < context.stackPtr - 2) {
                        result.add(m);
                    }
                    if (m.stackLoc == context.stackPtr - 1) {
                        result.add(new TypeMapping(context.stackPtr - 2, m.type));
                        result.add(new TypeMapping(context.stackPtr, m.type));
                    }
                    if (m.stackLoc == context.stackPtr - 2) {
                        result.add(new TypeMapping(context.stackPtr - 1, m.type));
                    }
                }
            }
            break;
        case Constants.DUP_X2:
            {
                for (TypeMapping m : in) {
                    if (m.stackLoc < context.stackPtr - 3) {
                        result.add(m);
                    }
                    if (m.stackLoc == context.stackPtr - 1) {
                        result.add(new TypeMapping(context.stackPtr - 3, m.type));
                        result.add(new TypeMapping(context.stackPtr, m.type));
                    }
                    if (m.stackLoc == context.stackPtr - 2) {
                        result.add(new TypeMapping(context.stackPtr - 1, m.type));
                    }
                    if (m.stackLoc == context.stackPtr - 3) {
                        result.add(new TypeMapping(context.stackPtr - 2, m.type));
                    }
                }
            }
            break;
        case Constants.DUP2:
            {
                for (TypeMapping m : in) {
                    result.add(m);
                    if (m.stackLoc == context.stackPtr - 2) {
                        result.add(new TypeMapping(context.stackPtr, m.type));
                    }
                    if (m.stackLoc == context.stackPtr - 1) {
                        result.add(new TypeMapping(context.stackPtr + 1, m.type));
                    }
                }
            }
            break;
        case Constants.DUP2_X1:
            {
                for (TypeMapping m : in) {
                    if (m.stackLoc < context.stackPtr - 3) {
                        result.add(m);
                    }
                    if (m.stackLoc == context.stackPtr - 2) {
                        result.add(new TypeMapping(context.stackPtr - 3, m.type));
                        result.add(new TypeMapping(context.stackPtr, m.type));
                    }
                    if (m.stackLoc == context.stackPtr - 1) {
                        result.add(new TypeMapping(context.stackPtr - 2, m.type));
                        result.add(new TypeMapping(context.stackPtr + 1, m.type));
                    }
                    if (m.stackLoc == context.stackPtr - 3) {
                        result.add(new TypeMapping(context.stackPtr - 1, m.type));
                    }
                }
            }
            break;
        case Constants.DUP2_X2:
            {
                for (TypeMapping m : in) {
                    if (m.stackLoc < context.stackPtr - 3) {
                        result.add(m);
                    }
                    if (m.stackLoc == context.stackPtr - 2) {
                        result.add(new TypeMapping(context.stackPtr - 4, m.type));
                        result.add(new TypeMapping(context.stackPtr, m.type));
                    }
                    if (m.stackLoc == context.stackPtr - 1) {
                        result.add(new TypeMapping(context.stackPtr - 3, m.type));
                        result.add(new TypeMapping(context.stackPtr + 1, m.type));
                    }
                    if (m.stackLoc == context.stackPtr - 4) {
                        result.add(new TypeMapping(context.stackPtr - 2, m.type));
                    }
                    if (m.stackLoc == context.stackPtr - 3) {
                        result.add(new TypeMapping(context.stackPtr - 1, m.type));
                    }
                }
            }
            break;
        case Constants.SWAP:
            {
                for (TypeMapping m : in) {
                    if (m.stackLoc < context.stackPtr - 2) {
                        result.add(m);
                    }
                    if (m.stackLoc == context.stackPtr - 2) {
                        result.add(new TypeMapping(context.stackPtr - 1, m.type));
                    }
                    if (m.stackLoc == context.stackPtr - 1) {
                        result.add(new TypeMapping(context.stackPtr - 2, m.type));
                    }
                }
            }
            break;
        case Constants.POP:
            filterSet(in, result, context.stackPtr - 1);
            break;
        case Constants.POP2:
            filterSet(in, result, context.stackPtr - 2);
            break;
        case Constants.GETFIELD:
            {
                GETFIELD instr = (GETFIELD) instruction;
                List<String> receivers = new LinkedList<String>();
                for (TypeMapping m : in) {
                    if (m.stackLoc < context.stackPtr - 1) {
                        result.add(m);
                    } else if (m.stackLoc == context.stackPtr - 1) {
                        receivers.add(m.type);
                    }
                }
                //			if (receivers.isEmpty()
                //				&& instr.getFieldType(context.constPool) != Type.INT) {
                //				System.out.println("GETFIELD not found: "+context.method+"@"+stmt+": "+instr.getFieldName(context.constPool));
                ////				System.exit(1);
                //			}
                DFATool p = interpreter.getDFATool();
                String fieldName = instr.getFieldName(context.constPool());
                for (String receiver : receivers) {
                    //String heapLoc = receiver + "." + instr.getFieldName(context.constPool);
                    //String namedLoc = receiver.split("@")[0] + "." + instr.getFieldName(context.constPool);
                    String className = receiver.split("@")[0];
                    ClassInfo classInfo = p.classForField(className, fieldName);
                    if (classInfo != null) {
                        String heapLoc = classInfo.getClassName() + "." + fieldName;
                        recordReceiver(stmt, context, heapLoc);
                        for (TypeMapping m : in) {
                            if (heapLoc.equals(m.heapLoc)) {
                                result.add(new TypeMapping(context.stackPtr - 1, m.type));
                            }
                        }
                    }
                }
            }
            break;
        case Constants.PUTFIELD:
            {
                PUTFIELD instr = (PUTFIELD) instruction;
                List<String> receivers = new LinkedList<String>();
                int fieldSize = instr.getFieldType(context.constPool()).getSize();
                for (TypeMapping m : in) {
                    if (m.stackLoc < context.stackPtr - 1 - fieldSize) {
                        result.add(m);
                    } else if (m.stackLoc == context.stackPtr - 1 - fieldSize) {
                        receivers.add(m.type);
                    }
                }
                //			if (receivers.isEmpty()) {
                //				System.out.println("PUTFIELD not found: "+context.method+"@"+stmt+": "+instr.getFieldName(context.constPool));
                ////				System.exit(-1);
                //			}
                DFATool p = interpreter.getDFATool();
                String fieldName = instr.getFieldName(context.constPool());
                for (String receiver : receivers) {
                    //String heapLoc = receiver + "." + instr.getFieldName(context.constPool);
                    //String namedLoc = receiver.split("@")[0] + "." + instr.getFieldName(context.constPool);
                    String className = receiver.split("@")[0];
                    ClassInfo classInfo = p.classForField(className, fieldName);
                    if (classInfo != null) {
                        String heapLoc = classInfo.getClassName() + "." + fieldName;
                        recordReceiver(stmt, context, heapLoc);
                        for (TypeMapping m : in) {
                            if (!heapLoc.equals(m.heapLoc) || context.threaded) {
                                result.add(m);
                            }
                            if (m.stackLoc == context.stackPtr - 1) {
                                result.add(new TypeMapping(heapLoc, m.type));
                            }
                        }
                    }
                }
                if (instr.getFieldType(context.constPool()) instanceof ReferenceType) {
                    doInvokeStatic("com.jopdesign.sys.JVM.f_putfield_ref(III)V", stmt, context, input, interpreter, state, retval);
                }
            }
            break;
        case Constants.GETSTATIC:
            {
                GETSTATIC instr = (GETSTATIC) instruction;
                DFATool p = interpreter.getDFATool();
                FieldRef ref = context.getMethodInfo().getCode().getFieldRef(instr);
                String fieldName = ref.getName();
                String className = ref.getClassName();
                ClassInfo classInfo = p.classForField(className, fieldName);
                if (classInfo != null) {
                    String heapLoc = classInfo.getClassName() + "." + fieldName;
                    recordReceiver(stmt, context, heapLoc);
                    for (TypeMapping m : in) {
                        if (m.stackLoc < context.stackPtr) {
                            result.add(m);
                        }
                        if (heapLoc.equals(m.heapLoc)) {
                            result.add(new TypeMapping(context.stackPtr, m.type));
                        }
                    }
                } else {
                //				System.out.println("GETSTATIC not found: "+heapLoc);
                //				System.exit(1);
                }
            }
            break;
        case Constants.PUTSTATIC:
            {
                PUTSTATIC instr = (PUTSTATIC) instruction;
                DFATool p = interpreter.getDFATool();
                FieldRef ref = context.getMethodInfo().getCode().getFieldRef(instr);
                String fieldName = ref.getName();
                String className = ref.getClassName();
                ClassInfo classInfo = p.classForField(className, fieldName);
                if (classInfo != null) {
                    String heapLoc = classInfo.getClassName() + "." + fieldName;
                    recordReceiver(stmt, context, heapLoc);
                    for (TypeMapping m : in) {
                        if (m.stackLoc >= 0 && m.stackLoc < context.stackPtr - 1) {
                            result.add(m);
                        } else if (m.stackLoc == -1 && (!heapLoc.equals(m.heapLoc) || context.threaded)) {
                            result.add(m);
                        }
                        if (m.stackLoc == context.stackPtr - 1) {
                            result.add(new TypeMapping(heapLoc, m.type));
                        }
                    }
                } else {
                //				System.out.println("PUTSTATIC not found: "+heapLoc);
                //				System.exit(1);
                }
                if (instr.getFieldType(context.constPool()) instanceof ReferenceType) {
                    doInvokeStatic("com.jopdesign.sys.JVM.f_putstatic_ref(II)V", stmt, context, input, interpreter, state, retval);
                }
            }
            break;
        case Constants.ARRAYLENGTH:
            for (TypeMapping m : in) {
                if (m.stackLoc < context.stackPtr - 1) {
                    result.add(m);
                }
                if (m.stackLoc == context.stackPtr - 1) {
                    recordReceiver(stmt, context, m.type);
                }
            }
            break;
        case Constants.IASTORE:
        case Constants.BASTORE:
        case Constants.CASTORE:
        case Constants.SASTORE:
        case Constants.FASTORE:
            {
                for (TypeMapping m : in) {
                    if (m.stackLoc < context.stackPtr - 3) {
                        result.add(m);
                    }
                    if (m.stackLoc == context.stackPtr - 3) {
                        recordReceiver(stmt, context, m.type);
                    }
                }
            }
            break;
        case Constants.LASTORE:
        case Constants.DASTORE:
            {
                for (TypeMapping m : in) {
                    if (m.stackLoc < context.stackPtr - 4) {
                        result.add(m);
                    }
                    if (m.stackLoc == context.stackPtr - 4) {
                        recordReceiver(stmt, context, m.type);
                    }
                }
            }
            break;
        case Constants.AASTORE:
            {
                List<String> receivers = new LinkedList<String>();
                for (TypeMapping m : in) {
                    if (m.stackLoc < context.stackPtr - 3) {
                        result.add(m);
                    } else if (m.stackLoc == context.stackPtr - 3) {
                        receivers.add(m.type);
                        recordReceiver(stmt, context, m.type);
                    }
                }
                for (String healLoc : receivers) {
                    for (TypeMapping m : in) {
                        if (m.stackLoc == context.stackPtr - 1) {
                            result.add(new TypeMapping(healLoc, m.type));
                        }
                    }
                }
                doInvokeStatic("com.jopdesign.sys.JVM.f_aastore(III)V", stmt, context, input, interpreter, state, retval);
            }
            break;
        case Constants.IALOAD:
        case Constants.BALOAD:
        case Constants.CALOAD:
        case Constants.SALOAD:
        case Constants.FALOAD:
            {
                for (TypeMapping m : in) {
                    if (m.stackLoc < context.stackPtr - 2) {
                        result.add(m);
                    }
                    if (m.stackLoc == context.stackPtr - 2) {
                        recordReceiver(stmt, context, m.type);
                    }
                }
            }
            break;
        case Constants.LALOAD:
        case Constants.DALOAD:
            {
                for (TypeMapping m : in) {
                    if (m.stackLoc < context.stackPtr - 2) {
                        result.add(m);
                    }
                    if (m.stackLoc == context.stackPtr - 2) {
                        recordReceiver(stmt, context, m.type);
                    }
                }
            }
            break;
        case Constants.AALOAD:
            {
                List<String> receivers = new LinkedList<String>();
                for (TypeMapping m : in) {
                    if (m.stackLoc < context.stackPtr - 2) {
                        result.add(m);
                    } else if (m.stackLoc == context.stackPtr - 2) {
                        receivers.add(m.type);
                        recordReceiver(stmt, context, m.type);
                    }
                }
                for (String heapLoc : receivers) {
                    for (TypeMapping m : in) {
                        if (heapLoc.equals(m.heapLoc)) {
                            result.add(new TypeMapping(context.stackPtr - 2, m.type));
                        }
                    }
                }
            }
            break;
        case Constants.NEW:
            {
                NEW instr = (NEW) instruction;
                filterSet(in, result, context.stackPtr);
                String name = instr.getType(context.constPool()).toString();
                name += "@" + context.method() + ":" + stmt.getPosition();
                result.add(new TypeMapping(context.stackPtr, name));
                doInvokeStatic("com.jopdesign.sys.JVM.f_" + stmt.getInstruction().getName() + "(I)I", stmt, context, input, interpreter, state, retval);
            }
            break;
        case Constants.ANEWARRAY:
            {
                ANEWARRAY instr = (ANEWARRAY) instruction;
                filterSet(in, result, context.stackPtr - 1);
                String name = instr.getType(context.constPool()).toString() + "[]";
                name += "@" + context.method() + ":" + stmt.getPosition();
                result.add(new TypeMapping(context.stackPtr - 1, name));
                doInvokeStatic("com.jopdesign.sys.JVM.f_" + stmt.getInstruction().getName() + "(II)I", stmt, context, input, interpreter, state, retval);
            }
            break;
        case Constants.NEWARRAY:
            {
                NEWARRAY instr = (NEWARRAY) instruction;
                filterSet(in, result, context.stackPtr - 1);
                String name = instr.getType().toString();
                name += "@" + context.method() + ":" + stmt.getPosition();
                result.add(new TypeMapping(context.stackPtr - 1, name));
                doInvokeStatic("com.jopdesign.sys.JVM.f_" + stmt.getInstruction().getName() + "(II)I", stmt, context, input, interpreter, state, retval);
            }
            break;
        case Constants.MULTIANEWARRAY:
            {
                MULTIANEWARRAY instr = (MULTIANEWARRAY) instruction;
                int dim = instr.getDimensions();
                filterSet(in, result, context.stackPtr - dim);
                String type = instr.getType(context.constPool()).toString();
                type = type.substring(0, type.indexOf("["));
                for (int i = 1; i <= dim; i++) {
                    String type1 = type;
                    String type2 = type;
                    for (int k = 0; k < i; k++) {
                        type1 += "[]";
                    }
                    for (int k = 0; k < i - 1; k++) {
                        type2 += "[]";
                    }
                    type1 += "@" + context.method() + ":" + stmt.getPosition();
                    type2 += "@" + context.method() + ":" + stmt.getPosition();
                    result.add(new TypeMapping(type1, type2));
                }
                String name = instr.getType(context.constPool()).toString();
                name += "@" + context.method() + ":" + stmt.getPosition();
                result.add(new TypeMapping(context.stackPtr - dim, name));
                doInvokeStatic("com.jopdesign.sys.JVM.f_" + stmt.getInstruction().getName() + "()I", stmt, context, input, interpreter, state, retval);
            }
            break;
        case Constants.ILOAD_0:
        case Constants.ILOAD_1:
        case Constants.ILOAD_2:
        case Constants.ILOAD_3:
        case Constants.ILOAD:
        case Constants.FLOAD_0:
        case Constants.FLOAD_1:
        case Constants.FLOAD_2:
        case Constants.FLOAD_3:
        case Constants.FLOAD:
        case Constants.LLOAD_0:
        case Constants.LLOAD_1:
        case Constants.LLOAD_2:
        case Constants.LLOAD_3:
        case Constants.LLOAD:
        case Constants.DLOAD_0:
        case Constants.DLOAD_1:
        case Constants.DLOAD_2:
        case Constants.DLOAD_3:
        case Constants.DLOAD:
            result = in;
            retval.put(context.callString, result);
            break;
        case Constants.ALOAD_0:
        case Constants.ALOAD_1:
        case Constants.ALOAD_2:
        case Constants.ALOAD_3:
        case Constants.ALOAD:
            {
                LoadInstruction instr = (LoadInstruction) instruction;
                int index = instr.getIndex();
                for (TypeMapping m : in) {
                    if (m.stackLoc < context.stackPtr) {
                        result.add(m);
                    }
                    if (m.stackLoc == index) {
                        result.add(new TypeMapping(context.stackPtr, m.type));
                    }
                }
            }
            break;
        case Constants.ISTORE_0:
        case Constants.ISTORE_1:
        case Constants.ISTORE_2:
        case Constants.ISTORE_3:
        case Constants.ISTORE:
        case Constants.FSTORE_0:
        case Constants.FSTORE_1:
        case Constants.FSTORE_2:
        case Constants.FSTORE_3:
        case Constants.FSTORE:
        case Constants.LSTORE_0:
        case Constants.LSTORE_1:
        case Constants.LSTORE_2:
        case Constants.LSTORE_3:
        case Constants.LSTORE:
        case Constants.DSTORE_0:
        case Constants.DSTORE_1:
        case Constants.DSTORE_2:
        case Constants.DSTORE_3:
        case Constants.DSTORE:
            result = in;
            retval.put(context.callString, result);
            break;
        case Constants.ASTORE_0:
        case Constants.ASTORE_1:
        case Constants.ASTORE_2:
        case Constants.ASTORE_3:
        case Constants.ASTORE:
            {
                StoreInstruction instr = (StoreInstruction) instruction;
                int index = instr.getIndex();
                for (TypeMapping m : in) {
                    if (m.stackLoc < context.stackPtr - 1 && m.stackLoc != index) {
                        result.add(m);
                    }
                    if (m.stackLoc == context.stackPtr - 1) {
                        result.add(new TypeMapping(index, m.type));
                    }
                }
            }
            break;
        case Constants.FCMPL:
        case Constants.FCMPG:
        case Constants.LCMP:
        case Constants.DCMPL:
        case Constants.DCMPG:
            result = in;
            retval.put(context.callString, result);
            break;
        case Constants.IFEQ:
        case Constants.IFNE:
        case Constants.IFLT:
        case Constants.IFGE:
        case Constants.IFGT:
        case Constants.IFLE:
        case Constants.IFNULL:
        case Constants.IFNONNULL:
            filterSet(in, result, context.stackPtr - 1);
            break;
        case Constants.IF_ICMPEQ:
        case Constants.IF_ICMPNE:
        case Constants.IF_ICMPLT:
        case Constants.IF_ICMPGE:
        case Constants.IF_ICMPGT:
        case Constants.IF_ICMPLE:
        case Constants.IF_ACMPEQ:
        case Constants.IF_ACMPNE:
            filterSet(in, result, context.stackPtr - 2);
            break;
        case Constants.TABLESWITCH:
        case Constants.LOOKUPSWITCH:
            filterSet(in, result, context.stackPtr - 1);
            break;
        case Constants.GOTO:
            result = in;
            retval.put(context.callString, result);
            break;
        case Constants.IADD:
        case Constants.ISUB:
        case Constants.IMUL:
        case Constants.IDIV:
        case Constants.IREM:
        case Constants.ISHL:
        case Constants.ISHR:
        case Constants.IUSHR:
        case Constants.IAND:
        case Constants.IOR:
        case Constants.IXOR:
        case Constants.FADD:
        case Constants.FSUB:
        case Constants.FMUL:
        case Constants.FDIV:
        case Constants.FREM:
        case Constants.DADD:
        case Constants.DSUB:
        case Constants.DMUL:
        case Constants.DDIV:
        case Constants.DREM:
        case Constants.IINC:
        case Constants.INEG:
        case Constants.FNEG:
        case Constants.LNEG:
        case Constants.DNEG:
        case Constants.LADD:
        case Constants.LAND:
        case Constants.LOR:
        case Constants.LXOR:
        case Constants.LSUB:
        case Constants.LSHL:
        case Constants.LSHR:
        case Constants.LUSHR:
            result = in;
            retval.put(context.callString, result);
            break;
        case Constants.LMUL:
        case Constants.LDIV:
        case Constants.LREM:
            result = new LinkedHashSet<TypeMapping>(in);
            retval.put(context.callString, result);
            doInvokeStatic("com.jopdesign.sys.JVM.f_" + stmt.getInstruction().getName() + "(JJ)J", stmt, context, input, interpreter, state, retval);
            break;
        case Constants.I2B:
        case Constants.I2C:
        case Constants.I2S:
        case Constants.I2F:
        case Constants.F2I:
        case Constants.I2L:
        case Constants.I2D:
        case Constants.F2L:
        case Constants.F2D:
        case Constants.L2I:
        case Constants.D2I:
        case Constants.L2F:
        case Constants.D2F:
        case Constants.L2D:
        case Constants.D2L:
            result = in;
            retval.put(context.callString, result);
            break;
        case Constants.INSTANCEOF:
            filterSet(in, result, context.stackPtr - 1);
            break;
        case Constants.CHECKCAST:
            {
                DFATool p = interpreter.getDFATool();
                CHECKCAST instr = (CHECKCAST) instruction;
                for (TypeMapping m : in) {
                    if (m.stackLoc < context.stackPtr - 1) {
                        result.add(m);
                    }
                    if (m.stackLoc == context.stackPtr - 1) {
                        // check whether this class can possibly be cast
                        String constClassName = instr.getType(context.constPool()).toString();
                        ClassInfo staticClass = p.getAppInfo().getClassInfo(constClassName);
                        ClassInfo dynamicClass = p.getAppInfo().getClassInfo(m.type.split("@")[0]);
                        //					System.out.println("CHECKCAST: "+context.callString.asList()+"/"+context.method+": "+stmt+": "+constClassName+" vs "+m.type);
                        if (dynamicClass.isSubclassOf(staticClass)) {
                            result.add(m);
                        //							System.out.println("yay!");
                        }
                    }
                }
            }
            break;
        case Constants.MONITORENTER:
            filterSet(in, result, context.stackPtr - 1);
            context.syncLevel++;
            break;
        case Constants.MONITOREXIT:
            filterSet(in, result, context.stackPtr - 1);
            context.syncLevel--;
            if (context.syncLevel < 0) {
                System.err.println("Synchronization level mismatch.");
                System.exit(-1);
            }
            break;
        case Constants.INVOKEVIRTUAL:
        case Constants.INVOKEINTERFACE:
            {
                InvokeInstruction instr = (InvokeInstruction) instruction;
                int argSize = MethodHelper.getArgSize(instr, context.constPool());
                DFATool p = interpreter.getDFATool();
                MethodRef ref = context.getMethodInfo().getCode().getInvokeSite(stmt).getInvokeeRef();
                ClassInfo constClass = ref.getClassInfo();
                // find possible receiver types
                List<String> receivers = new LinkedList<String>();
                for (TypeMapping m : in) {
                    if (m.stackLoc == context.stackPtr - argSize) {
                        String clName = m.type.split("@")[0];
                        ClassInfo dynamicClass;
                        // check whether this class can possibly be a receiver
                        try {
                            dynamicClass = p.getAppInfo().getClassInfo(clName);
                        } catch (MissingClassError ex) {
                            logger.error("TRANSFER/" + instr + ": " + ex);
                            continue;
                        }
                        if ((instr instanceof INVOKEVIRTUAL && dynamicClass.isSubclassOf(constClass)) || (instr instanceof INVOKEINTERFACE && dynamicClass.isImplementationOf(constClass))) {
                            receivers.add(clName);
                        } else {
                            logger.debug(context.method() + ": class " + constClass + " is not a superclass of " + clName);
                        }
                    }
                }
                /* Get the actual set of invoked methods */
                //ArrayList<MethodInfo> invokeCandidates = new ArrayList<MethodInfo>();
                String signature = ref.getMethodSignature();
                for (String receiver : receivers) {
                    // find receiving method
                    MethodInfo impl = p.getAppInfo().getMethodInfoInherited(receiver, signature);
                    if (impl == null) {
                        throw new AppInfoError("Could not find implementation for: " + receiver + "#" + signature);
                    }
                    doInvokeVirtual(receiver, impl, stmt, context, input, interpreter, state, retval);
                }
                // add relevant information to result
                filterSet(in, result, context.stackPtr - argSize);
            }
            break;
        case Constants.INVOKESTATIC:
        case Constants.INVOKESPECIAL:
            {
                InvokeInstruction instr = (InvokeInstruction) instruction;
                int argSize = MethodHelper.getArgSize(instr, context.constPool());
                MethodRef ref = context.getMethodInfo().getCode().getInvokeSite(stmt).getInvokeeRef();
                MethodInfo impl = ref.getMethodInfo();
                if (impl == null) {
                    throw new AppInfoError("Cannot find implementation of " + ref);
                } else if (impl.isPrivate() && !impl.isStatic()) {
                    doInvokeVirtual(ref.getClassName(), impl, stmt, context, input, interpreter, state, retval);
                } else {
                    doInvokeStatic(impl.getMemberID().toString(), stmt, context, input, interpreter, state, retval);
                }
                // add relevant information to result
                filterSet(in, result, context.stackPtr - argSize);
            }
            break;
        case Constants.RETURN:
        case Constants.IRETURN:
        case Constants.FRETURN:
        case Constants.LRETURN:
        case Constants.DRETURN:
            filterSet(in, result, 0);
            break;
        case Constants.ARETURN:
            {
                for (TypeMapping m : in) {
                    if (m.stackLoc < 0) {
                        result.add(m);
                    }
                    if (m.stackLoc == context.stackPtr - 1) {
                        result.add(new TypeMapping(0, m.type));
                    }
                }
            }
            break;
        default:
            System.out.println("Unknown opcode: " + instruction.toString(context.constPool().getConstantPool()));
            System.exit(-1);
    }
    //		System.out.print(instruction+":\t{ ");
    //		for (Iterator k = result.iterator(); k.hasNext(); ) {
    //			ReceiverTypes.TypeMapping m = (ReceiverTypes.TypeMapping) k.next();
    //			if (m.stackLoc >= 0) {
    //				System.out.print("<stack[" + m.stackLoc + "], " + m.type +">, ");
    //			} else {
    //				System.out.print("<" + m.heapLoc + ", " + m.type +">, ");						
    //			}
    //		}
    //		System.out.println("}");				
    //		System.out.println("AFTER "+context.method+": "+stmt+" / "+context.callString.asList());
    //		System.out.print(stmt.getInstruction()+":\t{ ");
    //		System.out.print(context.callString.asList()+": "+retval.get(context.callString));
    //		System.out.println(" }");
    context.stackPtr += instruction.produceStack(context.constPool()) - instruction.consumeStack(context.constPool());
    return retval;
}
Also used : LinkedHashSet(java.util.LinkedHashSet) NEW(org.apache.bcel.generic.NEW) LinkedHashSet(java.util.LinkedHashSet) Set(java.util.Set) MULTIANEWARRAY(org.apache.bcel.generic.MULTIANEWARRAY) ANEWARRAY(org.apache.bcel.generic.ANEWARRAY) CHECKCAST(org.apache.bcel.generic.CHECKCAST) LDC(org.apache.bcel.generic.LDC) CallString(com.jopdesign.common.code.CallString) InvokeInstruction(org.apache.bcel.generic.InvokeInstruction) LoadInstruction(org.apache.bcel.generic.LoadInstruction) StoreInstruction(org.apache.bcel.generic.StoreInstruction) Instruction(org.apache.bcel.generic.Instruction) ReferenceType(org.apache.bcel.generic.ReferenceType) AppInfoError(com.jopdesign.common.misc.AppInfoError) PUTSTATIC(org.apache.bcel.generic.PUTSTATIC) LoadInstruction(org.apache.bcel.generic.LoadInstruction) MethodRef(com.jopdesign.common.type.MethodRef) LinkedList(java.util.LinkedList) List(java.util.List) MissingClassError(com.jopdesign.common.misc.MissingClassError) Context(com.jopdesign.dfa.framework.Context) MULTIANEWARRAY(org.apache.bcel.generic.MULTIANEWARRAY) ANEWARRAY(org.apache.bcel.generic.ANEWARRAY) NEWARRAY(org.apache.bcel.generic.NEWARRAY) DFATool(com.jopdesign.dfa.DFATool) FieldRef(com.jopdesign.common.type.FieldRef) PUTFIELD(org.apache.bcel.generic.PUTFIELD) MULTIANEWARRAY(org.apache.bcel.generic.MULTIANEWARRAY) ContextMap(com.jopdesign.dfa.framework.ContextMap) CallString(com.jopdesign.common.code.CallString) GETFIELD(org.apache.bcel.generic.GETFIELD) InvokeInstruction(org.apache.bcel.generic.InvokeInstruction) ReferenceType(org.apache.bcel.generic.ReferenceType) Type(org.apache.bcel.generic.Type) INVOKEINTERFACE(org.apache.bcel.generic.INVOKEINTERFACE) MethodInfo(com.jopdesign.common.MethodInfo) GETSTATIC(org.apache.bcel.generic.GETSTATIC) StoreInstruction(org.apache.bcel.generic.StoreInstruction) INVOKEVIRTUAL(org.apache.bcel.generic.INVOKEVIRTUAL) ClassInfo(com.jopdesign.common.ClassInfo)

Aggregations

DFATool (com.jopdesign.dfa.DFATool)13 CallString (com.jopdesign.common.code.CallString)8 Context (com.jopdesign.dfa.framework.Context)8 ContextMap (com.jopdesign.dfa.framework.ContextMap)8 MethodInfo (com.jopdesign.common.MethodInfo)6 Set (java.util.Set)6 LinkedHashSet (java.util.LinkedHashSet)5 InstructionHandle (org.apache.bcel.generic.InstructionHandle)5 AppSetup (com.jopdesign.common.AppSetup)3 AppInfoError (com.jopdesign.common.misc.AppInfoError)3 LinkedHashMap (java.util.LinkedHashMap)3 GETFIELD (org.apache.bcel.generic.GETFIELD)3 GETSTATIC (org.apache.bcel.generic.GETSTATIC)3 Instruction (org.apache.bcel.generic.Instruction)3 LDC (org.apache.bcel.generic.LDC)3 LoadInstruction (org.apache.bcel.generic.LoadInstruction)3 PUTFIELD (org.apache.bcel.generic.PUTFIELD)3 PUTSTATIC (org.apache.bcel.generic.PUTSTATIC)3 ReferenceType (org.apache.bcel.generic.ReferenceType)3 StoreInstruction (org.apache.bcel.generic.StoreInstruction)3