Search in sources :

Example 1 with AbstractInsnNode

use of org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode in project kotlin by JetBrains.

the class FieldRemapper method foldFieldAccessChainIfNeeded.

@Nullable
private AbstractInsnNode foldFieldAccessChainIfNeeded(@NotNull List<AbstractInsnNode> capturedFieldAccess, int currentInstruction, @NotNull MethodNode node) {
    boolean checkParent = !isRoot() && currentInstruction < capturedFieldAccess.size() - 1;
    if (checkParent) {
        AbstractInsnNode transformed = parent.foldFieldAccessChainIfNeeded(capturedFieldAccess, currentInstruction + 1, node);
        if (transformed != null) {
            return transformed;
        }
    }
    FieldInsnNode insnNode = (FieldInsnNode) capturedFieldAccess.get(currentInstruction);
    if (canProcess(insnNode.owner, insnNode.name, true)) {
        insnNode.name = "$$$" + insnNode.name;
        insnNode.setOpcode(Opcodes.GETSTATIC);
        AbstractInsnNode next = capturedFieldAccess.get(0);
        while (next != insnNode) {
            AbstractInsnNode toDelete = next;
            next = next.getNext();
            node.instructions.remove(toDelete);
        }
        return capturedFieldAccess.get(capturedFieldAccess.size() - 1);
    }
    return null;
}
Also used : FieldInsnNode(org.jetbrains.org.objectweb.asm.tree.FieldInsnNode) AbstractInsnNode(org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode) Nullable(org.jetbrains.annotations.Nullable)

Example 2 with AbstractInsnNode

use of org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode in project kotlin by JetBrains.

the class LintDriver method isSuppressed.

// Unfortunately, ASMs nodes do not extend a common DOM node type with parent
// pointers, so we have to have multiple methods which pass in each type
// of node (class, method, field) to be checked.
/**
     * Returns whether the given issue is suppressed in the given method.
     *
     * @param issue the issue to be checked, or null to just check for "all"
     * @param classNode the class containing the issue
     * @param method the method containing the issue
     * @param instruction the instruction within the method, if any
     * @return true if there is a suppress annotation covering the specific
     *         issue on this method
     */
public boolean isSuppressed(@Nullable Issue issue, @NonNull ClassNode classNode, @NonNull MethodNode method, @Nullable AbstractInsnNode instruction) {
    if (method.invisibleAnnotations != null) {
        @SuppressWarnings("unchecked") List<AnnotationNode> annotations = method.invisibleAnnotations;
        return isSuppressed(issue, annotations);
    }
    // for members and <clinit> for static fields).
    if (instruction != null && method.name.charAt(0) == '<') {
        AbstractInsnNode next = LintUtils.getNextInstruction(instruction);
        if (next != null && next.getType() == AbstractInsnNode.FIELD_INSN) {
            FieldInsnNode fieldRef = (FieldInsnNode) next;
            FieldNode field = findField(classNode, fieldRef.owner, fieldRef.name);
            if (field != null && isSuppressed(issue, field)) {
                return true;
            }
        } else if (classNode.outerClass != null && classNode.outerMethod == null && isAnonymousClass(classNode)) {
            if (isSuppressed(issue, classNode)) {
                return true;
            }
        }
    }
    return false;
}
Also used : FieldNode(org.jetbrains.org.objectweb.asm.tree.FieldNode) AnnotationNode(org.jetbrains.org.objectweb.asm.tree.AnnotationNode) FieldInsnNode(org.jetbrains.org.objectweb.asm.tree.FieldInsnNode) AbstractInsnNode(org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode)

Example 3 with AbstractInsnNode

use of org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode in project kotlin by JetBrains.

the class ControlFlowGraph method create.

/**
     * Creates a new {@link ControlFlowGraph} and populates it with the flow
     * control for the given method. If the optional {@code initial} parameter is
     * provided with an existing graph, then the graph is simply populated, not
     * created. This allows subclassing of the graph instance, if necessary.
     *
     * @param initial usually null, but can point to an existing instance of a
     *            {@link ControlFlowGraph} in which that graph is reused (but
     *            populated with new edges)
     * @param classNode the class containing the method to be analyzed
     * @param method the method to be analyzed
     * @return a {@link ControlFlowGraph} with nodes for the control flow in the
     *         given method
     * @throws AnalyzerException if the underlying bytecode library is unable to
     *             analyze the method bytecode
     */
@NonNull
public static ControlFlowGraph create(@Nullable ControlFlowGraph initial, @NonNull ClassNode classNode, @NonNull MethodNode method) throws AnalyzerException {
    final ControlFlowGraph graph = initial != null ? initial : new ControlFlowGraph();
    final InsnList instructions = method.instructions;
    graph.mNodeMap = Maps.newHashMapWithExpectedSize(instructions.size());
    graph.mMethod = method;
    // Create a flow control graph using ASM5's analyzer. According to the ASM 4 guide
    // (download.forge.objectweb.org/asm/asm4-guide.pdf) there are faster ways to construct
    // it, but those require a lot more code.
    Analyzer analyzer = new Analyzer(new BasicInterpreter()) {

        @Override
        protected void newControlFlowEdge(int insn, int successor) {
            // Update the information as of whether the this object has been
            // initialized at the given instruction.
            AbstractInsnNode from = instructions.get(insn);
            AbstractInsnNode to = instructions.get(successor);
            graph.add(from, to);
        }

        @Override
        protected boolean newControlFlowExceptionEdge(int insn, TryCatchBlockNode tcb) {
            AbstractInsnNode from = instructions.get(insn);
            graph.exception(from, tcb);
            return super.newControlFlowExceptionEdge(insn, tcb);
        }

        @Override
        protected boolean newControlFlowExceptionEdge(int insn, int successor) {
            AbstractInsnNode from = instructions.get(insn);
            AbstractInsnNode to = instructions.get(successor);
            graph.exception(from, to);
            return super.newControlFlowExceptionEdge(insn, successor);
        }
    };
    analyzer.analyze(classNode.name, method);
    return graph;
}
Also used : TryCatchBlockNode(org.jetbrains.org.objectweb.asm.tree.TryCatchBlockNode) BasicInterpreter(org.jetbrains.org.objectweb.asm.tree.analysis.BasicInterpreter) InsnList(org.jetbrains.org.objectweb.asm.tree.InsnList) Analyzer(org.jetbrains.org.objectweb.asm.tree.analysis.Analyzer) AbstractInsnNode(org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode) NonNull(com.android.annotations.NonNull)

Example 4 with AbstractInsnNode

use of org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode in project kotlin by JetBrains.

the class ControlFlowGraph method dotDescribe.

private static String dotDescribe(Node node) {
    AbstractInsnNode instruction = node.instruction;
    if (instruction instanceof LabelNode) {
        return "Label";
    } else if (instruction instanceof LineNumberNode) {
        LineNumberNode lineNode = (LineNumberNode) instruction;
        return "Line " + lineNode.line;
    } else if (instruction instanceof FrameNode) {
        return "Stack Frame";
    } else if (instruction instanceof MethodInsnNode) {
        MethodInsnNode method = (MethodInsnNode) instruction;
        String cls = method.owner.substring(method.owner.lastIndexOf('/') + 1);
        cls = cls.replace('$', '.');
        return "Call " + cls + "#" + method.name;
    } else if (instruction instanceof FieldInsnNode) {
        FieldInsnNode field = (FieldInsnNode) instruction;
        String cls = field.owner.substring(field.owner.lastIndexOf('/') + 1);
        cls = cls.replace('$', '.');
        return "Field " + cls + "#" + field.name;
    } else if (instruction instanceof TypeInsnNode && instruction.getOpcode() == Opcodes.NEW) {
        return "New " + ((TypeInsnNode) instruction).desc;
    }
    StringBuilder sb = new StringBuilder();
    String opcodeName = getOpcodeName(instruction.getOpcode());
    sb.append(opcodeName);
    if (instruction instanceof IntInsnNode) {
        IntInsnNode in = (IntInsnNode) instruction;
        sb.append(" ").append(Integer.toString(in.operand));
    } else if (instruction instanceof LdcInsnNode) {
        LdcInsnNode ldc = (LdcInsnNode) instruction;
        sb.append(" ");
        if (ldc.cst instanceof String) {
            sb.append("\\\"");
        }
        sb.append(ldc.cst);
        if (ldc.cst instanceof String) {
            sb.append("\\\"");
        }
    }
    return sb.toString();
}
Also used : LabelNode(org.jetbrains.org.objectweb.asm.tree.LabelNode) FrameNode(org.jetbrains.org.objectweb.asm.tree.FrameNode) LdcInsnNode(org.jetbrains.org.objectweb.asm.tree.LdcInsnNode) MethodInsnNode(org.jetbrains.org.objectweb.asm.tree.MethodInsnNode) FieldInsnNode(org.jetbrains.org.objectweb.asm.tree.FieldInsnNode) IntInsnNode(org.jetbrains.org.objectweb.asm.tree.IntInsnNode) LineNumberNode(org.jetbrains.org.objectweb.asm.tree.LineNumberNode) TypeInsnNode(org.jetbrains.org.objectweb.asm.tree.TypeInsnNode) AbstractInsnNode(org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode)

Example 5 with AbstractInsnNode

use of org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode in project intellij-community by JetBrains.

the class NullableInterpreter method processState.

private void processState(State state) throws AnalyzerException {
    Conf conf = state.conf;
    int insnIndex = conf.insnIndex;
    List<Conf> history = state.history;
    boolean taken = state.taken;
    Frame<BasicValue> frame = conf.frame;
    AbstractInsnNode insnNode = methodNode.instructions.get(insnIndex);
    List<Conf> nextHistory = dfsTree.loopEnters[insnIndex] ? append(history, conf) : history;
    addComputed(insnIndex, state);
    execute(frame, insnNode, taken);
    if (subResult == NPE || top) {
        earlyResult = NPE;
        return;
    }
    if (subResult instanceof ConditionalNPE) {
        myResult = combineNullable(myResult, subResult);
    }
    int opcode = insnNode.getOpcode();
    switch(opcode) {
        case ARETURN:
            if (popValue(frame) instanceof ParamValue) {
                earlyResult = NPE;
            }
            return;
        case IRETURN:
        case LRETURN:
        case FRETURN:
        case DRETURN:
        case RETURN:
            return;
        default:
    }
    if (opcode == ATHROW) {
        if (taken) {
            earlyResult = NPE;
        }
        return;
    }
    if (opcode == IFNONNULL && popValue(frame) instanceof ParamValue) {
        int nextInsnIndex = insnIndex + 1;
        pendingPush(new State(++id, new Conf(nextInsnIndex, nextFrame), nextHistory, true, false));
        return;
    }
    if (opcode == IFNULL && popValue(frame) instanceof ParamValue) {
        int nextInsnIndex = methodNode.instructions.indexOf(((JumpInsnNode) insnNode).label);
        pendingPush(new State(++id, new Conf(nextInsnIndex, nextFrame), nextHistory, true, false));
        return;
    }
    if (opcode == IFEQ && popValue(frame) == InstanceOfCheckValue) {
        int nextInsnIndex = methodNode.instructions.indexOf(((JumpInsnNode) insnNode).label);
        pendingPush(new State(++id, new Conf(nextInsnIndex, nextFrame), nextHistory, true, false));
        return;
    }
    if (opcode == IFNE && popValue(frame) == InstanceOfCheckValue) {
        int nextInsnIndex = insnIndex + 1;
        pendingPush(new State(++id, new Conf(nextInsnIndex, nextFrame), nextHistory, true, false));
        return;
    }
    // general case
    for (int nextInsnIndex : controlFlow.transitions[insnIndex]) {
        Frame<BasicValue> nextFrame1 = nextFrame;
        if (controlFlow.errors[nextInsnIndex] && controlFlow.errorTransitions.contains(new Edge(insnIndex, nextInsnIndex))) {
            nextFrame1 = new Frame<>(frame);
            nextFrame1.clearStack();
            nextFrame1.push(ASMUtils.THROWABLE_VALUE);
        }
        pendingPush(new State(++id, new Conf(nextInsnIndex, nextFrame1), nextHistory, taken, false));
    }
}
Also used : AbstractInsnNode(org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode) Edge(com.intellij.codeInspection.bytecodeAnalysis.asm.ControlFlowGraph.Edge) BasicValue(org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue)

Aggregations

AbstractInsnNode (org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode)15 FieldInsnNode (org.jetbrains.org.objectweb.asm.tree.FieldInsnNode)7 MethodNode (org.jetbrains.org.objectweb.asm.tree.MethodNode)7 LineNumberNode (org.jetbrains.org.objectweb.asm.tree.LineNumberNode)6 MethodInsnNode (org.jetbrains.org.objectweb.asm.tree.MethodInsnNode)6 ClassNode (org.jetbrains.org.objectweb.asm.tree.ClassNode)5 FrameNode (org.jetbrains.org.objectweb.asm.tree.FrameNode)5 IntInsnNode (org.jetbrains.org.objectweb.asm.tree.IntInsnNode)5 LabelNode (org.jetbrains.org.objectweb.asm.tree.LabelNode)5 LdcInsnNode (org.jetbrains.org.objectweb.asm.tree.LdcInsnNode)5 TryCatchBlockNode (org.jetbrains.org.objectweb.asm.tree.TryCatchBlockNode)5 TypeInsnNode (org.jetbrains.org.objectweb.asm.tree.TypeInsnNode)5 InsnList (org.jetbrains.org.objectweb.asm.tree.InsnList)4 JumpInsnNode (org.jetbrains.org.objectweb.asm.tree.JumpInsnNode)4 NonNull (com.android.annotations.NonNull)3 List (java.util.List)2 Detector (com.android.tools.klint.detector.api.Detector)1 ClassScanner (com.android.tools.klint.detector.api.Detector.ClassScanner)1 Location (com.android.tools.klint.detector.api.Location)1 Edge (com.intellij.codeInspection.bytecodeAnalysis.asm.ControlFlowGraph.Edge)1