@Override protected AbstractInsnNode transformMultiANewArrayInsnNode(MethodNode mn, MultiANewArrayInsnNode arrayInsnNode) { String new_desc = ""; Type t = Type.getType(arrayInsnNode.desc); while (t.getSort() == Type.ARRAY) { new_desc += "["; t = t.getElementType(); } if (t.equals(Type.BOOLEAN_TYPE)) new_desc += "I"; else new_desc += t.getDescriptor(); arrayInsnNode.desc = new_desc; return arrayInsnNode; }
/** * Adds the array to the last created method. * * @param desc * the desc * @param length * the length * @return the class node builder */ public ClassNodeBuilder addArray(final String desc, final int... length) { if (isInterface) { return this; } final Type elementType = Type.getType(desc).getElementType(); if (length.length == 1) { addInsn(NodeHelper.getInsnNodeFor(Integer.valueOf(length[0]))); if (elementType.getDescriptor().startsWith("L")) { addInsn(new TypeInsnNode(Opcodes.ANEWARRAY, elementType.getInternalName())); } else { addInsn(new IntInsnNode(Opcodes.NEWARRAY, getSort(elementType))); } } else { for (final int currentLength : length) { addInsn(NodeHelper.getInsnNodeFor(Integer.valueOf(currentLength))); } addInsn(new MultiANewArrayInsnNode(desc, length.length)); } addInsn(new VarInsnNode(Opcodes.ASTORE, methodVarIndex)); lastMethodVarIndex = methodVarIndex; lastVarElementType = elementType; methodVarIndex++; return this; }
@Override public BasicValue naryOperation(final AbstractInsnNode insn, final List<? extends BasicValue> values) throws AnalyzerException { int opcode = insn.getOpcode(); if (opcode == MULTIANEWARRAY) { return newValue(Type.getType(((MultiANewArrayInsnNode) insn).desc)); } else if (opcode == INVOKEDYNAMIC) { return newValue(Type .getReturnType(((InvokeDynamicInsnNode) insn).desc)); } else { return newValue(Type.getReturnType(((MethodInsnNode) insn).desc)); } }
private void build(MultiANewArrayInsnNode insn, IRBuilder builder) { // Type of the full array. Type arrayType = Type.getObjectType(insn.desc); DexType dexArrayType = application.getType(arrayType); // Type of the members. Can itself be of array type, eg, 'int[]' for 'new int[x][y][]' DexType memberType = application.getTypeFromDescriptor(insn.desc.substring(insn.dims)); // Push an array containing the dimensions of the desired multi-dimensional array. DexType dimArrayType = application.getTypeFromDescriptor(INT_ARRAY_DESC); Slot[] slots = state.popReverse(insn.dims, Type.INT_TYPE); int[] dimensions = new int[insn.dims]; for (int i = 0; i < insn.dims; i++) { dimensions[i] = slots[i].register; } builder.addInvokeNewArray(dimArrayType, insn.dims, dimensions); int dimensionsDestTemp = state.push(INT_ARRAY_TYPE); builder.addMoveResult(MoveType.OBJECT, dimensionsDestTemp); // Push the class object for the member type of the array. int classDestTemp = state.push(CLASS_TYPE); builder.ensureBlockForThrowingInstruction(); builder.addConstClass(classDestTemp, memberType); // Create the actual multi-dimensional array using java.lang.reflect.Array::newInstance DexType reflectArrayClass = application.getTypeFromDescriptor(REFLECT_ARRAY_DESC); DexMethod newInstance = application.getMethod(reflectArrayClass, REFLECT_ARRAY_NEW_INSTANCE_NAME, REFLECT_ARRAY_NEW_INSTANCE_DESC); List<MoveType> argumentTypes = Arrays.asList(moveType(CLASS_TYPE), moveType(INT_ARRAY_TYPE)); List<Integer> argumentRegisters = Arrays.asList(classDestTemp, dimensionsDestTemp); builder.ensureBlockForThrowingInstruction(); builder.addInvoke(Invoke.Type.STATIC, newInstance, null, argumentTypes, argumentRegisters); // Pop the temporaries and push the final result. state.pop(); // classDestTemp. state.pop(); // dimensionsDestTemp. int result = state.push(arrayType); builder.addMoveResult(moveType(arrayType), result); // Insert cast check to satisfy verification. builder.ensureBlockForThrowingInstruction(); builder.addCheckCast(result, dexArrayType); }
public Value naryOperation(final AbstractInsnNode insn, final List values) throws AnalyzerException { if (insn.getOpcode() == MULTIANEWARRAY) { return newValue(Type.getType(((MultiANewArrayInsnNode) insn).desc)); } else { return newValue(Type.getReturnType(((MethodInsnNode) insn).desc)); } }
@Override public void handle(AbstractInsnNode node) throws IncorrectNodeException { super.handle(node); LOG.debug(logNode(node)); checkType(node, MultiANewArrayInsnNode.class); String desc = ((MultiANewArrayInsnNode)node).desc; int dims = ((MultiANewArrayInsnNode)node).dims; mState.getActiveStack().push(new ArrayCreationExpression(node.getOpcode(), desc, dims)); }
@Override public BasicValue naryOperation(final AbstractInsnNode insn, final List<? extends BasicValue> values) throws AnalyzerException { int opcode = insn.opcode(); if (opcode == MULTIANEWARRAY) { return newValue(Type.getType(((MultiANewArrayInsnNode) insn).desc)); } else if (opcode == INVOKEDYNAMIC) { return newValue(Type .getReturnType(((InvokeDynamicInsnNode) insn).desc)); } else { return newValue(Type.getReturnType(((MethodInsnNode) insn).desc)); } }
private void interpret(MultiANewArrayInsnNode insn, FrameState frame, BBInfo block) { assert insn.getOpcode() == Opcodes.MULTIANEWARRAY; Klass k = getKlassByInternalName(insn.desc); Value[] dims = new Value[insn.dims]; for (int i = dims.length-1; i >= 0; --i) dims[i] = frame.stack.pop(); NewArrayInst nai = new NewArrayInst(typeFactory.getArrayType(k), dims); block.block.instructions().add(nai); frame.stack.push(nai); }
private void emit(NewArrayInst i, InsnList insns) { ArrayType t = i.getType(); if (t.getDimensions() == 1) { load(i.getOperand(0), insns); RegularType ct = t.getComponentType(); if (ct instanceof PrimitiveType) { if (ct.equals(booleanType)) insns.add(new IntInsnNode(Opcodes.NEWARRAY, Opcodes.T_BOOLEAN)); else if (ct.equals(byteType)) insns.add(new IntInsnNode(Opcodes.NEWARRAY, Opcodes.T_BYTE)); else if (ct.equals(charType)) insns.add(new IntInsnNode(Opcodes.NEWARRAY, Opcodes.T_CHAR)); else if (ct.equals(shortType)) insns.add(new IntInsnNode(Opcodes.NEWARRAY, Opcodes.T_SHORT)); else if (ct.equals(intType)) insns.add(new IntInsnNode(Opcodes.NEWARRAY, Opcodes.T_INT)); else if (ct.equals(longType)) insns.add(new IntInsnNode(Opcodes.NEWARRAY, Opcodes.T_LONG)); else if (ct.equals(floatType)) insns.add(new IntInsnNode(Opcodes.NEWARRAY, Opcodes.T_FLOAT)); else if (ct.equals(doubleType)) insns.add(new IntInsnNode(Opcodes.NEWARRAY, Opcodes.T_DOUBLE)); } else { insns.add(new TypeInsnNode(Opcodes.ANEWARRAY, internalName(ct.getKlass()))); } } else { for (Value v : i.operands()) load(v, insns); insns.add(new MultiANewArrayInsnNode(t.getDescriptor(), i.getNumOperands())); } store(i, insns); }
@Override public BasicValue naryOperation(final AbstractInsnNode insn, final List<? extends BasicValue> values) throws AnalyzerException { int opcode = insn.getOpcode(); if (opcode == MULTIANEWARRAY) { return newValue(Type.getType(((MultiANewArrayInsnNode) insn).desc)); } else if (opcode == INVOKEDYNAMIC){ return newValue(Type.getReturnType(((InvokeDynamicInsnNode) insn).desc)); } else { return newValue(Type.getReturnType(((MethodInsnNode) insn).desc)); } }
/** * Registers values for local arrays that are created via NEWARRAY / ANEWARRAY or MULTIANEWARRAY. * * @param currentNode * the current node * @param knownArrays * the known arrays * @return true, if successful */ @Override protected int registerAdditionalValues(final AbstractInsnNode currentNode, // final Map<Integer, Object> knownArrays) { final int opcode = currentNode.getOpcode(); if (!((opcode == Opcodes.NEWARRAY) || (opcode == Opcodes.ANEWARRAY) || (opcode == Opcodes.MULTIANEWARRAY))) { return 0; } int dims = 1; if (currentNode.getOpcode() == Opcodes.MULTIANEWARRAY) { final MultiANewArrayInsnNode node = (MultiANewArrayInsnNode) currentNode; dims = node.dims; } final int sizes[] = new int[dims]; AbstractInsnNode previous = currentNode; for (int i = 0; i < dims; ++i) { previous = NodeHelper.getPrevious(previous); if (!NodeHelper.isIntNode(previous)) { return 0; } try { final int value = NodeHelper.getNumberValue(previous).intValue(); sizes[i] = value; } catch (final NotANumberException nane) { return 0; } } final AbstractInsnNode next = NodeHelper.getNext(currentNode); if (!(next instanceof VarInsnNode)) { return 0; } final int index = ((VarInsnNode) next).var; knownArrays.put(Integer.valueOf(index), Array.newInstance(Object.class, sizes)); return 2; }
private void updateState(AbstractInsnNode insn) { switch (insn.getType()) { case AbstractInsnNode.INSN: updateState((InsnNode) insn); break; case AbstractInsnNode.INT_INSN: updateState((IntInsnNode) insn); break; case AbstractInsnNode.VAR_INSN: updateState((VarInsnNode) insn); break; case AbstractInsnNode.TYPE_INSN: updateState((TypeInsnNode) insn); break; case AbstractInsnNode.FIELD_INSN: updateState((FieldInsnNode) insn); break; case AbstractInsnNode.METHOD_INSN: updateState((MethodInsnNode) insn); break; case AbstractInsnNode.INVOKE_DYNAMIC_INSN: updateState((InvokeDynamicInsnNode) insn); break; case AbstractInsnNode.JUMP_INSN: updateState((JumpInsnNode) insn); break; case AbstractInsnNode.LABEL: updateState((LabelNode) insn); break; case AbstractInsnNode.LDC_INSN: updateState((LdcInsnNode) insn); break; case AbstractInsnNode.IINC_INSN: updateState((IincInsnNode) insn); break; case AbstractInsnNode.TABLESWITCH_INSN: updateState((TableSwitchInsnNode) insn); break; case AbstractInsnNode.LOOKUPSWITCH_INSN: updateState((LookupSwitchInsnNode) insn); break; case AbstractInsnNode.MULTIANEWARRAY_INSN: updateState((MultiANewArrayInsnNode) insn); break; case AbstractInsnNode.LINE: updateState((LineNumberNode) insn); break; default: throw new Unreachable("Unexpected instruction " + insn); } }
private void updateState(MultiANewArrayInsnNode insn) { // Type of the full array. Type arrayType = Type.getObjectType(insn.desc); state.popReverse(insn.dims, Type.INT_TYPE); state.push(arrayType); }
private void build(AbstractInsnNode insn, IRBuilder builder) { switch (insn.getType()) { case AbstractInsnNode.INSN: build((InsnNode) insn, builder); break; case AbstractInsnNode.INT_INSN: build((IntInsnNode) insn, builder); break; case AbstractInsnNode.VAR_INSN: build((VarInsnNode) insn, builder); break; case AbstractInsnNode.TYPE_INSN: build((TypeInsnNode) insn, builder); break; case AbstractInsnNode.FIELD_INSN: build((FieldInsnNode) insn, builder); break; case AbstractInsnNode.METHOD_INSN: build((MethodInsnNode) insn, builder); break; case AbstractInsnNode.INVOKE_DYNAMIC_INSN: build((InvokeDynamicInsnNode) insn, builder); break; case AbstractInsnNode.JUMP_INSN: build((JumpInsnNode) insn, builder); break; case AbstractInsnNode.LABEL: build((LabelNode) insn, builder); break; case AbstractInsnNode.LDC_INSN: build((LdcInsnNode) insn, builder); break; case AbstractInsnNode.IINC_INSN: build((IincInsnNode) insn, builder); break; case AbstractInsnNode.TABLESWITCH_INSN: build((TableSwitchInsnNode) insn, builder); break; case AbstractInsnNode.LOOKUPSWITCH_INSN: build((LookupSwitchInsnNode) insn, builder); break; case AbstractInsnNode.MULTIANEWARRAY_INSN: build((MultiANewArrayInsnNode) insn, builder); break; case AbstractInsnNode.LINE: build((LineNumberNode) insn, builder); break; default: throw new Unreachable("Unexpected instruction " + insn); } }
AsmMultiANewArrayInsnReference(AsmItem source, MultiANewArrayInsnNode insn, boolean isStrong) { super(source, REF_FULL, isStrong); this.insn = insn; }
@Override public final void visitMultiANewArrayInsn(String desc, int dims) { MultiANewArrayInsnNode node = new MultiANewArrayInsnNode(desc, dims); instructions.add(node); addFrame(node); }
/** * <p>transform</p> * * @param mn a {@link org.objectweb.asm.tree.MethodNode} object. */ public void transform(MethodNode mn) { setupLocals(mn); Set<AbstractInsnNode> originalNodes = new HashSet<AbstractInsnNode>(); AbstractInsnNode node = mn.instructions.getFirst(); while (node != mn.instructions.getLast()) { originalNodes.add(node); node = node.getNext(); } //int currentIndex = 0; node = mn.instructions.getFirst(); //while (currentIndex < mn.instructions.size()) { boolean finished = false; while (!finished) { //while (node != mn.instructions.getLast()) { //node = mn.instructions.get(currentIndex); //int oldLength = mn.instructions.size(); // BytecodeInstruction insn = BytecodeInstructionPool.getInstruction(className, // mn.name // + mn.desc, // node); // if (insn == null) { // // if (!originalNodes.contains(node)) { // System.out.println("Node not present in original stuff " + node); // // Only transform nodes present in original method // } else if (node instanceof MethodInsnNode) { node = transformMethodInsnNode(mn, (MethodInsnNode) node); } else if (node instanceof VarInsnNode) { node = transformVarInsnNode(mn, (VarInsnNode) node); } else if (node instanceof FieldInsnNode) { node = transformFieldInsnNode(mn, (FieldInsnNode) node); } else if (node instanceof InsnNode) { node = transformInsnNode(mn, (InsnNode) node); } else if (node instanceof TypeInsnNode) { node = transformTypeInsnNode(mn, (TypeInsnNode) node); } else if (node instanceof JumpInsnNode) { node = transformJumpInsnNode(mn, (JumpInsnNode) node); } else if (node instanceof LabelNode) { node = transformLabelNode(mn, (LabelNode) node); } else if (node instanceof IntInsnNode) { node = transformIntInsnNode(mn, (IntInsnNode) node); } else if (node instanceof MultiANewArrayInsnNode) { node = transformMultiANewArrayInsnNode(mn, (MultiANewArrayInsnNode) node); } //currentIndex += mn.instructions.size() - oldLength; //currentIndex++; if (node == mn.instructions.getLast()) { finished = true; } else { node = node.getNext(); } } }
public static TreeSize getTreeSize(AbstractInsnNode ain) { int c = 0, p = 0; if (ain instanceof InsnNode || ain instanceof IntInsnNode || ain instanceof VarInsnNode || ain instanceof JumpInsnNode || ain instanceof TableSwitchInsnNode || ain instanceof LookupSwitchInsnNode) { c = CDS[ain.opcode()]; p = PDS[ain.opcode()]; } else if (ain instanceof FieldInsnNode) { FieldInsnNode fin = (FieldInsnNode) ain; char d = fin.desc.charAt(0); switch (fin.opcode()) { case GETFIELD: { c = 1; p = d == 'D' || d == 'J' ? 2 : 1; break; } case GETSTATIC: { c = 0; p = d == 'D' || d == 'J' ? 2 : 1; break; } case PUTFIELD: { c = d == 'D' || d == 'J' ? 3 : 2; p = 0; break; } case PUTSTATIC: { c = d == 'D' || d == 'J' ? 2 : 1; p = 0; break; } default: { c = 0; p = 0; break; } } } else if (ain instanceof MethodInsnNode) { MethodInsnNode min = (MethodInsnNode) ain; int as = Type.getArgumentsAndReturnSizes(min.desc); c = (as >> 2) - (min.opcode() == INVOKEDYNAMIC || min.opcode() == INVOKESTATIC ? 1 : 0); p = as & 0x03; } else if (ain instanceof LdcInsnNode) { Object cst = ((LdcInsnNode) ain).cst; p = cst instanceof Double || cst instanceof Long ? 2 : 1; } else if (ain instanceof MultiANewArrayInsnNode) { c = ((MultiANewArrayInsnNode) ain).dims; p = 1; } return new TreeSize(c, p); }
public static boolean instructionsEqual(AbstractInsnNode insn1, AbstractInsnNode insn2) { if (insn1 == insn2) { return true; } if (insn1 == null || insn2 == null || insn1.type() != insn2.type() || insn1.opcode() != insn2.opcode()) { return false; } int size; switch (insn1.type()) { case INSN: return true; case INT_INSN: IntInsnNode iin1 = (IntInsnNode) insn1, iin2 = (IntInsnNode) insn2; return iin1.operand == iin2.operand; case VAR_INSN: VarInsnNode vin1 = (VarInsnNode) insn1, vin2 = (VarInsnNode) insn2; return vin1.var == vin2.var; case TYPE_INSN: TypeInsnNode tin1 = (TypeInsnNode) insn1, tin2 = (TypeInsnNode) insn2; return tin1.desc.equals(tin2.desc); case FIELD_INSN: FieldInsnNode fin1 = (FieldInsnNode) insn1, fin2 = (FieldInsnNode) insn2; return fin1.desc.equals(fin2.desc) && fin1.name.equals(fin2.name) && fin1.owner.equals(fin2.owner); case METHOD_INSN: MethodInsnNode min1 = (MethodInsnNode) insn1, min2 = (MethodInsnNode) insn2; return min1.desc.equals(min2.desc) && min1.name.equals(min2.name) && min1.owner.equals(min2.owner); case INVOKE_DYNAMIC_INSN: InvokeDynamicInsnNode idin1 = (InvokeDynamicInsnNode) insn1, idin2 = (InvokeDynamicInsnNode) insn2; return idin1.bsm.equals(idin2.bsm) && Arrays.equals(idin1.bsmArgs, idin2.bsmArgs) && idin1.desc.equals(idin2.desc) && idin1.name.equals(idin2.name); case JUMP_INSN: JumpInsnNode jin1 = (JumpInsnNode) insn1, jin2 = (JumpInsnNode) insn2; return instructionsEqual(jin1.label, jin2.label); case LABEL: Label label1 = ((LabelNode) insn1).getLabel(), label2 = ((LabelNode) insn2).getLabel(); return label1 == null ? label2 == null : label1.info == null ? label2.info == null : label1.info.equals(label2.info); case LDC_INSN: LdcInsnNode lin1 = (LdcInsnNode) insn1, lin2 = (LdcInsnNode) insn2; return lin1.cst.equals(lin2.cst); case IINC_INSN: IincInsnNode iiin1 = (IincInsnNode) insn1, iiin2 = (IincInsnNode) insn2; return iiin1.incr == iiin2.incr && iiin1.var == iiin2.var; case TABLESWITCH_INSN: TableSwitchInsnNode tsin1 = (TableSwitchInsnNode) insn1, tsin2 = (TableSwitchInsnNode) insn2; size = tsin1.labels.size(); if (size != tsin2.labels.size()) { return false; } for (int i = 0; i < size; i++) { if (!instructionsEqual(tsin1.labels.get(i), tsin2.labels.get(i))) { return false; } } return instructionsEqual(tsin1.dflt, tsin2.dflt) && tsin1.max == tsin2.max && tsin1.min == tsin2.min; case LOOKUPSWITCH_INSN: LookupSwitchInsnNode lsin1 = (LookupSwitchInsnNode) insn1, lsin2 = (LookupSwitchInsnNode) insn2; size = lsin1.labels.size(); if (size != lsin2.labels.size()) { return false; } for (int i = 0; i < size; i++) { if (!instructionsEqual(lsin1.labels.get(i), lsin2.labels.get(i))) { return false; } } return instructionsEqual(lsin1.dflt, lsin2.dflt) && lsin1.keys.equals(lsin2.keys); case MULTIANEWARRAY_INSN: MultiANewArrayInsnNode manain1 = (MultiANewArrayInsnNode) insn1, manain2 = (MultiANewArrayInsnNode) insn2; return manain1.desc.equals(manain2.desc) && manain1.dims == manain2.dims; case FRAME: FrameNode fn1 = (FrameNode) insn1, fn2 = (FrameNode) insn2; return fn1.local.equals(fn2.local) && fn1.stack.equals(fn2.stack); case LINE: LineNumberNode lnn1 = (LineNumberNode) insn1, lnn2 = (LineNumberNode) insn2; return lnn1.line == lnn2.line && instructionsEqual(lnn1.start, lnn2.start); } return false; }
public static String toString(AbstractInsnNode insn) { if (insn == null) { return "null"; } int op = insn.opcode(); if (op == -1) { return insn.toString(); } StringBuilder sb = new StringBuilder(); /* pad the opcode name so that all the extra information for the instructions is aligned on the column. * TODO: maybe change the column length to the longest opcode name in the instruction set rather than * out of all the possible ones(statically, the longest opcode name is invokedynamic).*/ sb.append(pad(OPCODES[op].toLowerCase(), LONGEST_OPCODE_NAME)); switch (insn.type()) { case INT_INSN: sb.append(((IntInsnNode) insn).operand); break; case VAR_INSN: sb.append('#').append(((VarInsnNode) insn).var); break; case TYPE_INSN: sb.append(((TypeInsnNode) insn).desc); break; case FIELD_INSN: FieldInsnNode fin = (FieldInsnNode) insn; sb.append(fin.owner).append('.').append(fin.name).append(' ').append(fin.desc); break; case METHOD_INSN: MethodInsnNode min = (MethodInsnNode) insn; sb.append(min.owner).append('.').append(min.name).append(' ').append(min.desc); break; case JUMP_INSN: break; case LDC_INSN: Object cst = ((LdcInsnNode) insn).cst; sb.append(cst).append("(").append(cst.getClass().getName()).append(")"); break; case IINC_INSN: IincInsnNode iin = (IincInsnNode) insn; sb.append('#').append(iin.var).append(' ').append(iin.incr); break; case TABLESWITCH_INSN: break; case LOOKUPSWITCH_INSN: break; case MULTIANEWARRAY_INSN: MultiANewArrayInsnNode m = (MultiANewArrayInsnNode) insn; sb.append(m.desc).append(' ').append(m.dims); break; } return sb.toString(); }
public MultiNewArrayInstruction(MethodElement method, MultiANewArrayInsnNode node) { super(method, node); }
public CodeBlock multianewarray(final String arrayDesc, final int dims) { instructionList.add(new MultiANewArrayInsnNode(arrayDesc, dims)); return this; }
public CodeBlock visitMultiANewArrayInsn(final String desc, final int dims) { instructionList.add(new MultiANewArrayInsnNode(desc, dims)); return this; }
public void testClassRemapper() throws Exception { Map<String, String> map = new HashMap<String, String>(); map.put("Boo", "B1"); map.put("Coo", "C1"); map.put("Doo", "D1"); Remapper remapper = new SimpleRemapper(map); ClassNode cn = new ClassNode(); dump(new ClassRemapper(cn, remapper)); assertEquals("D1", cn.name); assertEquals("B1", cn.superName); assertEquals(Arrays.asList(new String[] { "I", "I", "C1", "J", "B1" }), cn.interfaces); assertEquals("LB1;", field(cn, 0).desc); assertEquals("[LB1;", field(cn, 1).desc); assertEquals("D1", innerClass(cn, 0).name); assertEquals("B1", innerClass(cn, 0).outerName); // assertEquals("Doo", innerClass(cn, 0).innerName); assertEquals("B1", cn.outerClass); assertEquals("([[LB1;LC1;LD1;)LC1;", cn.outerMethodDesc); MethodNode mn0 = cn.methods.get(0); ListIterator<AbstractInsnNode> it = mn0.instructions.iterator(); FieldInsnNode n0 = (FieldInsnNode) it.next(); assertEquals("D1", n0.owner); assertEquals("LB1;", n0.desc); assertEquals(Type.getType("LB1;"), ((LdcInsnNode) it.next()).cst); assertEquals(Type.getType("[LD1;"), ((LdcInsnNode) it.next()).cst); assertEquals(Type.getType("[I"), ((LdcInsnNode) it.next()).cst); assertEquals(Type.getType("J"), ((LdcInsnNode) it.next()).cst); assertEquals("B1", ((TypeInsnNode) it.next()).desc); assertEquals("[LD1;", ((TypeInsnNode) it.next()).desc); assertEquals("[I", ((TypeInsnNode) it.next()).desc); assertEquals("J", ((TypeInsnNode) it.next()).desc); MultiANewArrayInsnNode n3 = (MultiANewArrayInsnNode) it.next(); assertEquals("[[LB1;", n3.desc); MethodInsnNode n4 = (MethodInsnNode) it.next(); assertEquals("D1", n4.owner); assertEquals("([[LB1;LC1;LD1;)LC1;", n4.desc); FrameNode fn0 = (FrameNode) it.next(); assertEquals(Collections.EMPTY_LIST, fn0.local); assertEquals(Collections.EMPTY_LIST, fn0.stack); assertEquals(Arrays.asList(new Object[] { "B1", "C1", "D1" }), ((FrameNode) it.next()).local); assertEquals( Arrays.asList(new Object[] { Opcodes.INTEGER, "C1", Opcodes.INTEGER, "D1" }), ((FrameNode) it.next()).local); assertEquals(Arrays.asList(new Object[] { Opcodes.INTEGER, Opcodes.INTEGER }), ((FrameNode) it.next()).local); // assertEquals(Collections.EMPTY_LIST, fn0.stack); TryCatchBlockNode tryCatchBlockNode = mn0.tryCatchBlocks.get(0); assertEquals("C1", tryCatchBlockNode.type); MethodNode mn1 = cn.methods.get(1); assertEquals("([[LB1;LC1;LD1;)V", mn1.desc); assertEquals(Arrays.asList(new String[] { "I", "J" }), mn1.exceptions); }
private void buildInstructions(BBInfo block) { FrameState frame = block.entryState.copy(); for (int i = block.start; i < block.end; ++i) { AbstractInsnNode insn = methodNode.instructions.get(i); if (insn.getOpcode() == -1) continue;//pseudo-instruction node if (insn instanceof FieldInsnNode) interpret((FieldInsnNode)insn, frame, block); else if (insn instanceof IincInsnNode) interpret((IincInsnNode)insn, frame, block); else if (insn instanceof InsnNode) interpret((InsnNode)insn, frame, block); else if (insn instanceof IntInsnNode) interpret((IntInsnNode)insn, frame, block); else if (insn instanceof InvokeDynamicInsnNode) interpret((InvokeDynamicInsnNode)insn, frame, block); else if (insn instanceof JumpInsnNode) interpret((JumpInsnNode)insn, frame, block); else if (insn instanceof LdcInsnNode) interpret((LdcInsnNode)insn, frame, block); else if (insn instanceof LookupSwitchInsnNode) interpret((LookupSwitchInsnNode)insn, frame, block); else if (insn instanceof MethodInsnNode) interpret((MethodInsnNode)insn, frame, block); else if (insn instanceof MultiANewArrayInsnNode) interpret((MultiANewArrayInsnNode)insn, frame, block); else if (insn instanceof TableSwitchInsnNode) interpret((TableSwitchInsnNode)insn, frame, block); else if (insn instanceof TypeInsnNode) interpret((TypeInsnNode)insn, frame, block); else if (insn instanceof VarInsnNode) interpret((VarInsnNode)insn, frame, block); } //If the block doesn't have a TerminatorInst, add a JumpInst to the //fallthrough block. (This occurs when blocks begin due to being a //jump target rather than due to a terminator opcode.) if (block.block.getTerminator() == null) block.block.instructions().add(new JumpInst(blocks.get(blocks.indexOf(block)+1).block)); for (BasicBlock b : block.block.successors()) for (BBInfo bi : blocks) if (bi.block == b) { merge(block, frame, bi); break; } }
private void transformMultiANewArrayInsn(final MultiANewArrayInsnNode insn) { // create a new int array to hold the dimensions and fill the dimensions in there. // then push the dimensions back onto the stack, call the MULTIANEWARRAY instruction // and afterward, call a method that gets the dimensions array and the newly // created array and traces the object ids. this.instructionIterator.previous(); this.instructionIterator.add(getIntConstInsn(insn.dims)); this.instructionIterator.add(new IntInsnNode(NEWARRAY, Opcodes.T_INT)); // now fill in the dimensions for (int dim = insn.dims-1; dim >= 0; --dim) { this.instructionIterator.add(new InsnNode(DUP_X1)); this.instructionIterator.add(new InsnNode(SWAP)); this.instructionIterator.add(getIntConstInsn(dim)); this.instructionIterator.add(new InsnNode(SWAP)); this.instructionIterator.add(new InsnNode(IASTORE)); } // duplicate the array reference this.instructionIterator.add(new InsnNode(DUP)); // push the dimensions back onto the stack for (int dim = 0; dim < insn.dims; ++dim) { // don't duplicate if this is the last entry if (dim != insn.dims-1) this.instructionIterator.add(new InsnNode(DUP)); this.instructionIterator.add(getIntConstInsn(dim)); this.instructionIterator.add(new InsnNode(IALOAD)); // swap with the reference below us if (dim != insn.dims-1) this.instructionIterator.add(new InsnNode(SWAP)); } this.instructionIterator.next(); final int newObjCountSeqIndex = this.tracer.newIntegerTraceSequence(); final int newObjIdSeqIndex = this.tracer.newLongTraceSequence(); // now call the original MULTIANEWARRAY instruction registerInstruction(new MultiANewArrayInstruction(this.readMethod, this.currentLine, insn.desc, insn.dims, newObjCountSeqIndex, newObjIdSeqIndex), InstructionType.UNSAFE); // and now call a tracing method that gets the dimensions array, the newly // created multi-dimensional array, and the sequence ids this.instructionIterator.add(new InsnNode(DUP_X1)); this.instructionIterator.add(new VarInsnNode(ALOAD, this.tracerLocalVarIndex)); this.instructionIterator.add(getIntConstInsn(newObjCountSeqIndex)); this.instructionIterator.add(getIntConstInsn(newObjIdSeqIndex)); this.instructionIterator.add(new MethodInsnNode(INVOKESTATIC, Type.getInternalName(TracingMethodInstrumenter.class), "traceMultiANewArray", "([I[Ljava/lang/Object;"+Type.getDescriptor(ThreadTracer.class)+"II)V", false)); }