Mercurial > hg > icedrobot > daneel
changeset 40:aa501bc3bdd7
Implemented rewriting of const32 and range invoke.
Contributed-by: Remi Forax
* dexlib/DexLibDexReader.java: See above.
* rewriter/DexRewriter.java: Likewise.
* (newAssertionError): Throw exception explicitly in every method.
author | Michael Starzinger <michi@complang.tuwien.ac.at> |
---|---|
date | Fri, 18 Mar 2011 01:39:50 +0100 |
parents | 3e21c5b61980 |
children | 0dc9d18f2633 |
files | src/main/java/org/icedrobot/daneel/dex/dexlib/DexLibDexReader.java src/main/java/org/icedrobot/daneel/rewriter/DexRewriter.java |
diffstat | 2 files changed, 118 insertions(+), 67 deletions(-) [+] |
line wrap: on
line diff
--- a/src/main/java/org/icedrobot/daneel/dex/dexlib/DexLibDexReader.java Fri Mar 18 01:07:56 2011 +0100 +++ b/src/main/java/org/icedrobot/daneel/dex/dexlib/DexLibDexReader.java Fri Mar 18 01:39:50 2011 +0100 @@ -62,18 +62,14 @@ import org.jf.dexlib.StringIdItem; import org.jf.dexlib.TypeIdItem; import org.jf.dexlib.TypeListItem; +import org.jf.dexlib.Code.FiveRegisterInstruction; import org.jf.dexlib.Code.Instruction; import org.jf.dexlib.Code.InstructionWithReference; import org.jf.dexlib.Code.LiteralInstruction; +import org.jf.dexlib.Code.RegisterRangeInstruction; import org.jf.dexlib.Code.SingleRegisterInstruction; import org.jf.dexlib.Code.Format.Instruction21c; -import org.jf.dexlib.Code.Format.Instruction21h; -import org.jf.dexlib.Code.Format.Instruction21s; import org.jf.dexlib.Code.Format.Instruction22c; -import org.jf.dexlib.Code.Format.Instruction31c; -import org.jf.dexlib.Code.Format.Instruction31i; -import org.jf.dexlib.Code.Format.Instruction35c; -import org.jf.dexlib.Code.Format.Instruction51l; import org.jf.dexlib.EncodedValue.BooleanEncodedValue; import org.jf.dexlib.EncodedValue.ByteEncodedValue; import org.jf.dexlib.EncodedValue.CharEncodedValue; @@ -337,6 +333,13 @@ break; } + case INSTR_CONST_U32: { + int vdest = ((SingleRegisterInstruction) instr).getRegisterA(); + long value = ((LiteralInstruction) instr).getLiteral(); + mv.visitInstrConstU32(opcode, vdest, (int)value); + break; + } + case INSTR_CONST_U64: { int vdest = ((SingleRegisterInstruction) instr).getRegisterA(); long value = ((LiteralInstruction) instr).getLiteral(); @@ -353,16 +356,28 @@ break; } - case INSTR_METHOD: { // TODO implement range !!! - Instruction35c i35c = (Instruction35c) instr; - MethodIdItem methodIdItem = (MethodIdItem) i35c.getReferencedItem(); + case INSTR_METHOD: { + int va, vpacked, size; + if (instr instanceof RegisterRangeInstruction) { // range + RegisterRangeInstruction rangeInstr = (RegisterRangeInstruction)instr; + size = rangeInstr.getRegCount(); + va = rangeInstr.getStartRegister(); + vpacked = 0; + } else { // packed + FiveRegisterInstruction fiveInstr = (FiveRegisterInstruction)instr; + size = fiveInstr.getRegCount(); + va = fiveInstr.getRegisterA(); + vpacked = fiveInstr.getRegisterG() << 12 | fiveInstr.getRegisterF() << 8 + | fiveInstr.getRegisterE() << 4 | fiveInstr.getRegisterD(); + } + InstructionWithReference refInstr = (InstructionWithReference) instr; + MethodIdItem methodIdItem = (MethodIdItem) refInstr.getReferencedItem(); String desc = methodIdItem.getPrototype().getPrototypeString(); - int vpacked = i35c.getRegisterG() << 12 | i35c.getRegisterF() << 8 - | i35c.getRegisterE() << 4 | i35c.getRegisterD(); - mv.visitInstrMethod(opcode, i35c.getRegCount(), - i35c.getRegisterA(), vpacked, + mv.visitInstrMethod(opcode, + size, va, vpacked, methodIdItem.getContainingClass().getTypeDescriptor(), - methodIdItem.getMethodName().getStringValue(), desc); + methodIdItem.getMethodName().getStringValue(), + desc); break; }
--- a/src/main/java/org/icedrobot/daneel/rewriter/DexRewriter.java Fri Mar 18 01:07:56 2011 +0100 +++ b/src/main/java/org/icedrobot/daneel/rewriter/DexRewriter.java Fri Mar 18 01:39:50 2011 +0100 @@ -178,8 +178,8 @@ return getTypeFromASMType(Type.getReturnType(descriptor)); } - private static void throwNewAssertionError(Opcode opcode) { - throw new AssertionError("invalid opcode " + opcode); + private static AssertionError newAssertionError(Opcode opcode) { + return new AssertionError("Invalid opcode: " + opcode); } @Override @@ -199,7 +199,7 @@ mv.visitInsn(NOP); return; } - throwNewAssertionError(opcode); + throw newAssertionError(opcode); } @Override @@ -235,7 +235,7 @@ mv.visitFieldInsn(PUTSTATIC, owner, name, desc); interpreter.load(vsrcOrDest, type); } else { - throwNewAssertionError(opcode); + throw newAssertionError(opcode); } } @@ -249,47 +249,90 @@ @Override public void visitInstrMethod(Opcode opcode, int num, int va, int vpacked, String owner, String name, String desc) { - owner = TypeUtil.convertDescToInternal(owner); - switch (opcode) { - case INVOKE_VIRTUAL: - case INVOKE_STATIC: - case INVOKE_SUPER: - case INVOKE_DIRECT: - int javaOpcode; - int[] registers = { getRegisterD(vpacked), + + Opcode erasedRangeOpcode; + int[] registers; + if (opcode.compareTo(Opcode.INVOKE_VIRTUAL_RANGE) >= 0) { // *_range + registers = null; + erasedRangeOpcode = Opcode.getOpcode(opcode.ordinal() + - INVOKE_RANGE_SHIFT); + } else { + registers = new int[] { getRegisterD(vpacked), getRegisterE(vpacked), getRegisterF(vpacked), getRegisterG(vpacked), va }; - int r; - if (opcode == Opcode.INVOKE_STATIC) { - r = 0; - javaOpcode = INVOKESTATIC; - } else { - r = 1; - javaOpcode = (opcode == Opcode.INVOKE_SUPER) ? INVOKESPECIAL - : (opcode == Opcode.INVOKE_DIRECT && "<init>" - .equals(name)) ? INVOKESPECIAL - : INVOKEVIRTUAL; - int register = registers[0]; - mv.visitVarInsn(ALOAD, register); - interpreter.load(register, OBJECT_TYPE); - } + erasedRangeOpcode = opcode; + } + + int javaOpcode; + switch (erasedRangeOpcode) { + case INVOKE_STATIC: + javaOpcode = INVOKESTATIC; + break; + case INVOKE_SUPER: + javaOpcode = INVOKESPECIAL; + break; + case INVOKE_VIRTUAL: + javaOpcode = INVOKEVIRTUAL; + break; + case INVOKE_INTERFACE: + javaOpcode = INVOKEINTERFACE; + break; + case INVOKE_DIRECT: + javaOpcode = ("<init>".equals(name)) ? INVOKESPECIAL + : INVOKEVIRTUAL; + break; + default: + throw newAssertionError(opcode); + } + + // We need to load the receiver first. + int r; + if (erasedRangeOpcode != Opcode.INVOKE_STATIC) { + r = 1; + int register = (registers == null) ? va : registers[0]; + mv.visitVarInsn(ALOAD, register); + interpreter.load(register, OBJECT_TYPE); + } else { + r = 0; + } - Type[] types = Type.getArgumentTypes(desc); - for (int i = 0; i < types.length; i++) { - Type asmType = types[i]; - int type = getTypeFromASMType(asmType); - int register = registers[r]; - mv.visitVarInsn(Register.getJavaOpcode(type, ILOAD), - register); - interpreter.load(register, type); - r += asmType.getSize(); + Type[] types = Type.getArgumentTypes(desc); + for (Type asmType : types) { + int type = getTypeFromASMType(asmType); + int register = (registers == null) ? va + r : registers[r]; + mv.visitVarInsn(Register.getJavaOpcode(type, ILOAD), register); + interpreter.load(register, type); + r += asmType.getSize(); + } + + owner = TypeUtil.convertDescToInternal(owner); + mv.visitMethodInsn(javaOpcode, owner, name, desc); + returnRegisterType = getReturnTypeFromMethodDescriptor(desc); + return; + } + + private static final int INVOKE_RANGE_SHIFT = + Opcode.INVOKE_VIRTUAL_RANGE.ordinal() - + Opcode.INVOKE_VIRTUAL.ordinal(); + + @Override + public void visitInstrConstU32(Opcode opcode, final int vdest, + final int value) { + mv.setPatchMode(); + mv.visitLdcInsn(value); + final AbstractInsnNode ldc = mv.getLastInsnNode(); + mv.visitVarInsn(ISTORE, vdest); + final AbstractInsnNode istore = mv.getLastInsnNode(); + interpreter.storeArbitraryType(vdest, U32_TYPE, new Patchable() { + @Override + protected void patch(int registerType) { + if (registerType == FLOAT_TYPE) { + mv.patch(ldc, new LdcInsnNode(Float + .intBitsToFloat(value))); + mv.patch(istore, new VarInsnNode(FSTORE, vdest)); + } } - mv.visitMethodInsn(javaOpcode, owner, name, desc); - returnRegisterType = getReturnTypeFromMethodDescriptor(desc); - return; - default: - throwNewAssertionError(opcode); - } + }); } @Override @@ -342,11 +385,6 @@ } @Override - public void visitInstrConstU32(Opcode opcode, int vdest, int value) { - throw new UnsupportedOperationException("NYI: " + opcode); - } - - @Override public void visitInstrFillArrayData(Opcode opcode, int vsrc, Object arrayData) { throw new UnsupportedOperationException("NYI" + opcode); @@ -403,16 +441,14 @@ } @Override + public void visitTryCatch(Label start, Label end, Label handler, String type) { + throw new UnsupportedOperationException("NYI"); + } + + @Override public void visitEnd() { mv.visitMaxs(-1, -1); mv.visitEnd(); } - - @Override - public void visitTryCatch(Label start, Label end, Label handler, - String type) { - // TODO Auto-generated method stub - - } } }