Search in sources :

Example 1 with Context

use of com.jopdesign.dfa.framework.Context 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 Context

use of com.jopdesign.dfa.framework.Context 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 Context

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

the class SymbolicPointsTo method printResult.

public void printResult(DFATool program) {
    Map<String, String> getFields = new TreeMap<String, String>();
    for (InstructionHandle instr : usedRefs.keySet()) {
        ContextMap<CallString, BoundedSet<SymbolicAddress>> r = usedRefs.get(instr);
        Context c = r.getContext();
        MethodInfo method = c.getMethodInfo();
        if (method == null) {
            throw new AssertionError("Internal Error: No method '" + c.method() + "'");
        }
        LineNumberTable lines = method.getCode().getLineNumberTable();
        int sourceLine = lines.getSourceLine(instr.getPosition());
        for (CallString callString : r.keySet()) {
            System.out.println(c.method() + ":" + sourceLine + ":" + callString + ": " + instr);
            BoundedSet<SymbolicAddress> symAddr = r.get(callString);
            String infoStr;
            if (instr.getInstruction() instanceof GETFIELD) {
                GETFIELD gfInstr = (GETFIELD) instr.getInstruction();
                infoStr = String.format("GETFIELD %s %s %s", symAddr.toString(), gfInstr.getFieldName(c.constPool()), gfInstr.getFieldType(c.constPool()));
            } else if (instr.getInstruction() instanceof ARRAYLENGTH) {
                infoStr = String.format("ARRAYLENGTH %s", symAddr.toString());
            } else if (instr.getInstruction() instanceof ArrayInstruction) {
                ArrayInstruction aInstr = (ArrayInstruction) instr.getInstruction();
                infoStr = String.format("%s %s %s[]", aInstr.getName().toUpperCase(), symAddr.toString(), aInstr.getType(c.constPool()));
            } else {
                infoStr = String.format("%s %s", instr.getInstruction().getName().toUpperCase(), symAddr.toString());
            }
            if (infoStr != null) {
                String infoKey = String.format("%s:%04d:%s", c.method(), sourceLine, callString);
                while (getFields.containsKey(infoKey)) infoKey += "'";
                getFields.put(infoKey, infoStr);
            }
        }
    }
    for (Entry<String, String> entry : getFields.entrySet()) {
        System.out.println(entry.getKey());
        System.out.println("  " + entry.getValue());
    }
}
Also used : Context(com.jopdesign.dfa.framework.Context) ARRAYLENGTH(org.apache.bcel.generic.ARRAYLENGTH) CallString(com.jopdesign.common.code.CallString) TreeMap(java.util.TreeMap) InstructionHandle(org.apache.bcel.generic.InstructionHandle) LineNumberTable(org.apache.bcel.classfile.LineNumberTable) CallString(com.jopdesign.common.code.CallString) BoundedSet(com.jopdesign.dfa.framework.BoundedSetFactory.BoundedSet) GETFIELD(org.apache.bcel.generic.GETFIELD) ArrayInstruction(org.apache.bcel.generic.ArrayInstruction) MethodInfo(com.jopdesign.common.MethodInfo)

Example 4 with Context

use of com.jopdesign.dfa.framework.Context 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 5 with Context

use of com.jopdesign.dfa.framework.Context 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)

Aggregations

Context (com.jopdesign.dfa.framework.Context)20 CallString (com.jopdesign.common.code.CallString)17 ContextMap (com.jopdesign.dfa.framework.ContextMap)17 InstructionHandle (org.apache.bcel.generic.InstructionHandle)10 Set (java.util.Set)9 MethodInfo (com.jopdesign.common.MethodInfo)8 DFATool (com.jopdesign.dfa.DFATool)8 LinkedHashSet (java.util.LinkedHashSet)8 LinkedHashMap (java.util.LinkedHashMap)7 Map (java.util.Map)6 GETFIELD (org.apache.bcel.generic.GETFIELD)4 ReferenceType (org.apache.bcel.generic.ReferenceType)4 Type (org.apache.bcel.generic.Type)4 AppInfoError (com.jopdesign.common.misc.AppInfoError)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