# HG changeset patch # User forax # Date 1301321208 -7200 # Node ID 2a82664dd5cd32e14bebef6f44fa1645fe50acf9 # Parent cb75377db25b9a5bca2229e5175ee2c90e6886a4 Untyped U32 are considered as int by if-eqz/if-nez/if-eq/if-ne. - visitInstrTest/visitInstrTestZ know consider U32 as itself. - Patchable.union should use doPatch instead of patch - join-point processing is refactored in one method: createOrMergeJoinPoint diff -r cb75377db25b -r 2a82664dd5cd src/main/java/org/icedrobot/daneel/rewriter/DalvikToJVMEncoder.java --- a/src/main/java/org/icedrobot/daneel/rewriter/DalvikToJVMEncoder.java Mon Mar 28 16:01:16 2011 +0200 +++ b/src/main/java/org/icedrobot/daneel/rewriter/DalvikToJVMEncoder.java Mon Mar 28 16:06:48 2011 +0200 @@ -175,8 +175,6 @@ Opcode.GOTO, Opcodes.GOTO, GOTO_16, Opcodes.GOTO, - IF_EQZ, IFEQ, - IF_NEZ, IFNE, IF_LTZ, IFLT, IF_GEZ, IFGE, IF_GTZ, IFGT, diff -r cb75377db25b -r 2a82664dd5cd src/main/java/org/icedrobot/daneel/rewriter/DexRewriter.java --- a/src/main/java/org/icedrobot/daneel/rewriter/DexRewriter.java Mon Mar 28 16:01:16 2011 +0200 +++ b/src/main/java/org/icedrobot/daneel/rewriter/DexRewriter.java Mon Mar 28 16:06:48 2011 +0200 @@ -65,6 +65,8 @@ import org.objectweb.asm.Type; import org.objectweb.asm.tree.AbstractInsnNode; import org.objectweb.asm.tree.InsnNode; +import org.objectweb.asm.tree.JumpInsnNode; +import org.objectweb.asm.tree.LabelNode; import org.objectweb.asm.tree.LdcInsnNode; import org.objectweb.asm.tree.VarInsnNode; @@ -286,6 +288,15 @@ } } + private void createOrMergeJoinPoint(Label label) { + Register[] registers = interpreter.getJoinPoint(label); + if (registers != null) { // backward jump + interpreter.merge(registers); + } else { // forward jump + interpreter.cloneJoinPoint(label); + } + } + private void visitNotInstr(int type) { org.objectweb.asm.Label falsePart = new org.objectweb.asm.Label(); org.objectweb.asm.Label endPart = new org.objectweb.asm.Label(); @@ -583,6 +594,7 @@ mv.visitVarInsn(Register.getJavaOpcode(type, ILOAD), srcOrDst); interpreter.load(srcOrDst, type); mv.visitInsn(Register.getJavaOpcode(type, IRETURN)); + interpreter.setDead(); break; } case MOVE_RESULT: @@ -609,6 +621,9 @@ mv.visitVarInsn(ALOAD, srcOrDst); interpreter.load(srcOrDst, OBJECT_TYPE); mv.visitInsn(toJavaOpcode[opcode.ordinal()]); + if (opcode == Opcode.THROW) { + interpreter.setDead(); + } } } @@ -794,45 +809,144 @@ fixStackAfterAMethodCallOrAnExceptionHandler(); exceptionOnTop = exceptionHandlerSet.contains(label); - Register[] registers = interpreter.getJoinPoint(label); - if (registers != null) { // target of an already seen jump - interpreter.merge(registers); - } else { // perhaps a control flow join point, save state - interpreter.cloneJoinPoint(label); - } + createOrMergeJoinPoint(label); mv.visitLabel(getASMLabel(label)); } @Override public void visitInstrGoto(Opcode opcode, Label label) { fixStackAfterAMethodCallOrAnExceptionHandler(); - Register[] registers = interpreter.getJoinPoint(label); - if (registers != null) { // backward goto - interpreter.merge(registers); - } else { // forward goto - interpreter.cloneJoinPoint(label); - } + createOrMergeJoinPoint(label); mv.visitJumpInsn(GOTO, getASMLabel(label)); interpreter.setDead(); } @Override - public void visitInstrIfTestZ(Opcode opcode, int vsrc, Label label) { + public void visitInstrIfTestZ(final Opcode opcode, int vsrc, Label label) { fixStackAfterAMethodCallOrAnExceptionHandler(); - vsrc = registerToSlot(vsrc); - mv.visitVarInsn(ILOAD, vsrc); - interpreter.load(vsrc, INT_TYPE); - - Register[] registers = interpreter.getJoinPoint(label); - if (registers != null) { // backward jump - interpreter.merge(registers); - } else { // forward jump - interpreter.cloneJoinPoint(label); + final int ssrc = registerToSlot(vsrc); + + int type, javaOpcode; + final org.objectweb.asm.Label asmLabel = getASMLabel(label); + if (opcode == Opcode.IF_EQZ || opcode == Opcode.IF_NEZ) { + final Register register = interpreter.getRegister(ssrc); + int srcType = register.getType(); + if (srcType == U32_TYPE) { + mv.visitVarInsn(ILOAD, ssrc); + final AbstractInsnNode iload = mv.getLastInsnNode(); + javaOpcode = (opcode == Opcode.IF_EQZ)? IFEQ: IFNE; + mv.visitJumpInsn(javaOpcode, asmLabel); + final AbstractInsnNode jump = mv.getLastInsnNode(); + + interpreter.storeUntypedType(ssrc, U32_TYPE, new Patchable() { + @Override + protected void patch(int registerType) { + register.getPatchable().doPatch(registerType); + if (registerType == OBJECT_TYPE || Register.isArray(registerType)) { + mv.patch(iload, new VarInsnNode(ALOAD, ssrc)); + int javaOpcode = (opcode == Opcode.IF_EQZ)? IFNULL: IFNONNULL; + mv.patch(jump, new JumpInsnNode(javaOpcode, new LabelNode(asmLabel))); + return; + } + } + }); + + createOrMergeJoinPoint(label); + return; + } + + if (srcType == OBJECT_TYPE || Register.isArray(srcType)) { + type = OBJECT_TYPE; + javaOpcode = (opcode == Opcode.IF_EQZ)? IFNULL: IFNONNULL; + } else { // a numeric type convertible to an int + type = INT_TYPE; + javaOpcode = (opcode == Opcode.IF_EQZ)? IFEQ: IFNE; + } + } else { // IF_LTZ, IF_GEZ, IF_GTZ, IF_LEZ + type = INT_TYPE; + javaOpcode = toJavaOpcode[opcode.ordinal()]; } - org.objectweb.asm.Label asmLabel = getASMLabel(label); - mv.visitJumpInsn(toJavaOpcode[opcode.ordinal()], asmLabel); + mv.visitVarInsn(Register.getJavaOpcode(type, ILOAD), ssrc); + interpreter.load(ssrc, type); + mv.visitJumpInsn(javaOpcode, asmLabel); + + createOrMergeJoinPoint(label); + } + + @Override + public void visitInstrIfTest(final Opcode opcode, int vvsrc1, int vvsrc2, + Label label) { + fixStackAfterAMethodCallOrAnExceptionHandler(); + final int vsrc1 = registerToSlot(vvsrc1); + final int vsrc2 = registerToSlot(vvsrc2); + + int type, javaOpcode; + final org.objectweb.asm.Label asmLabel = getASMLabel(label); + if (opcode == Opcode.IF_EQ || opcode == Opcode.IF_NE) { + final Register register1 = interpreter.getRegister(vsrc1); + int src1Type = register1.getType(); + final Register register2 = interpreter.getRegister(vsrc2); + int src2Type = register2.getType(); + + if (src1Type == U32_TYPE && src2Type == U32_TYPE) { + mv.visitVarInsn(ILOAD, vsrc1); + final AbstractInsnNode iload1 = mv.getLastInsnNode(); + mv.visitVarInsn(ILOAD, vsrc2); + final AbstractInsnNode iload2 = mv.getLastInsnNode(); + javaOpcode = (opcode == Opcode.IF_EQ)? IF_ICMPEQ: IF_ICMPNE; + mv.visitJumpInsn(javaOpcode, asmLabel); + final AbstractInsnNode jump = mv.getLastInsnNode(); + + final Patchable patchableUnion = (register1 == register2)? register1.getPatchable(): + Patchable.union(register1.getPatchable(), register2.getPatchable()); + + Patchable patchable = new Patchable() { + @Override + protected void patch(int registerType) { + patchableUnion.doPatch(registerType); + if (registerType == OBJECT_TYPE || Register.isArray(registerType)) { + mv.patch(iload1, new VarInsnNode(ALOAD, vsrc1)); + mv.patch(iload2, new VarInsnNode(ALOAD, vsrc2)); + int javaOpcode = (opcode == Opcode.IF_EQ)? IF_ACMPEQ: IF_ACMPNE; + mv.patch(jump, new JumpInsnNode(javaOpcode, new LabelNode(asmLabel))); + return; + } + } + }; + interpreter.storeUntypedType(vsrc1, U32_TYPE, patchable); + if (vsrc1 != vsrc2) { + interpreter.storeUntypedType(vsrc2, U32_TYPE, patchable); + } + + createOrMergeJoinPoint(label); + return; + } + + if (src1Type == OBJECT_TYPE || src2Type == OBJECT_TYPE + || Register.isArray(src1Type) + || Register.isArray(src2Type)) { + type = OBJECT_TYPE; + javaOpcode = (opcode == Opcode.IF_EQ) ? IF_ACMPEQ + : IF_ACMPNE; + } else { // a numeric type convertible to an int + type = INT_TYPE; + javaOpcode = (opcode == Opcode.IF_EQ) ? IF_ICMPEQ + : IF_ICMPNE; + } + } else { // IF_LT, IF_GE, IF_GT, IF_LE + type = INT_TYPE; + javaOpcode = toJavaOpcode[opcode.ordinal()]; + } + + mv.visitVarInsn(Register.getJavaOpcode(type, ILOAD), vsrc1); + interpreter.load(vsrc1, type); + mv.visitVarInsn(Register.getJavaOpcode(type, ILOAD), vsrc2); + interpreter.load(vsrc2, type); + mv.visitJumpInsn(javaOpcode, asmLabel); + + createOrMergeJoinPoint(label); } @Override @@ -903,39 +1017,6 @@ } @Override - public void visitInstrIfTest(Opcode opcode, int vsrc1, int vsrc2, - Label label) { - fixStackAfterAMethodCallOrAnExceptionHandler(); - vsrc1 = registerToSlot(vsrc1); - vsrc2 = registerToSlot(vsrc2); - org.objectweb.asm.Label asmLabel = getASMLabel(label); - if (opcode == Opcode.IF_EQ || opcode == Opcode.IF_NE) { - int src1Type = interpreter.getRegister(vsrc1).getType(); - int src2Type = interpreter.getRegister(vsrc2).getType(); - int javaOpcode; - int type; - if (src1Type == INT_TYPE || src2Type == INT_TYPE) { - type = INT_TYPE; - javaOpcode = (opcode == Opcode.IF_EQ)? IF_ICMPEQ: IF_ICMPNE; - } else { // OBJECT_TYPE or array - type = OBJECT_TYPE; - javaOpcode = (opcode == Opcode.IF_EQ)? IF_ACMPEQ: IF_ACMPNE; - } - mv.visitVarInsn(Register.getJavaOpcode(type, ILOAD), vsrc1); - interpreter.load(vsrc1, OBJECT_TYPE); - mv.visitVarInsn(Register.getJavaOpcode(type, ILOAD), vsrc2); - interpreter.load(vsrc2, OBJECT_TYPE); - mv.visitJumpInsn(javaOpcode, asmLabel); - } else { // IF_LT, IF_GE, IF_GT, IF_LE - mv.visitVarInsn(ILOAD, vsrc1); - interpreter.load(vsrc1, INT_TYPE); - mv.visitVarInsn(ILOAD, vsrc2); - interpreter.load(vsrc2, INT_TYPE); - mv.visitJumpInsn(toJavaOpcode[opcode.ordinal()], asmLabel); - } - } - - @Override public void visitTryCatch(Label start, Label end, Label handler, String type) { exceptionHandlerSet.add(handler); type = (type == null)? null: TypeUtil.convertDescToInternal(type); @@ -1013,7 +1094,7 @@ static final int[] toJavaOpcode; static { // this string is generated using DalvikToJVMEncoder - String text = "AA@@@@@@@@@@@@@@@@@@@@@@@@@@LB@@@@@@@@@@@@@@@@@@@@@@@@@@@@MCMDMAMBLOLLLM@@@@@@LPKHKHKH@@@@JFJGJHJIJE@@@@KBKCKDKEJJJKJLJMJNJO@@@@@@@@@@@@@@@@DCDDDDDEDF@@@@FDFEFEFFFG@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@HE@@HF@@HGHHIFIGIHIIIJIKILIMINIOIPJAJBJCJDGAGEGIGMHAGAIAICHIHKHMGBGFGJGNHBHPIBIDHJHLHNGCGGGKGOHCGDGHGLGPHDGAGEGIGMHAHOIAICHIHKHMGBGFGJGNHBHPIBIDHJHLHNGCGGGKGOHCGDGHGLGPHDGAGEGIGMHAGAIAICGAGEGIGMHAHOIAICHIHKHM@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"; + String text = "AA@@@@@@@@@@@@@@@@@@@@@@@@@@LB@@@@@@@@@@@@@@@@@@@@@@@@@@@@MCMDMAMBLOLLLM@@@@@@LPKHKHKH@@@@JFJGJHJIJE@@@@KBKCKDKE@@@@JLJMJNJO@@@@@@@@@@@@@@@@DCDDDDDEDF@@@@FDFEFEFFFG@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@HE@@HF@@HGHHIFIGIHIIIJIKILIMINIOIPJAJBJCJDGAGEGIGMHAGAIAICHIHKHMGBGFGJGNHBHPIBIDHJHLHNGCGGGKGOHCGDGHGLGPHDGAGEGIGMHAHOIAICHIHKHMGBGFGJGNHBHPIBIDHJHLHNGCGGGKGOHCGDGHGLGPHDGAGEGIGMHAGAIAICGAGEGIGMHAHOIAICHIHKHM@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"; int[] array = new int[256]; int length = text.length(); for (int i = 0; i < length; i += 2) { diff -r cb75377db25b -r 2a82664dd5cd src/main/java/org/icedrobot/daneel/rewriter/Patchable.java --- a/src/main/java/org/icedrobot/daneel/rewriter/Patchable.java Mon Mar 28 16:01:16 2011 +0200 +++ b/src/main/java/org/icedrobot/daneel/rewriter/Patchable.java Mon Mar 28 16:06:48 2011 +0200 @@ -59,8 +59,8 @@ return new Patchable() { @Override protected void patch(int registerType) { - patchable1.patch(registerType); - patchable2.patch(registerType); + patchable1.doPatch(registerType); + patchable2.doPatch(registerType); } }; }