Mercurial > hg > icedrobot > daneel
changeset 45:1b283cb77127
Perform mapping between calling conventions.
Contributed-by: Remi Forax
* dex/dexlib/DexLibDexReader.java: Correctly pass inWords and outWords.
* rewriter/DexRewriter.java: Map Dalvik registers to Java slots correctly.
* rewriter/Registers.java (packRegisters): New utility method.
author | Michael Starzinger <michi@complang.tuwien.ac.at> |
---|---|
date | Sat, 19 Mar 2011 15:37:50 +0100 |
parents | e47fc744d6b4 |
children | bac8d9297f30 |
files | src/main/java/org/icedrobot/daneel/dex/dexlib/DexLibDexReader.java src/main/java/org/icedrobot/daneel/rewriter/DexRewriter.java src/main/java/org/icedrobot/daneel/rewriter/Registers.java |
diffstat | 3 files changed, 98 insertions(+), 22 deletions(-) [+] |
line wrap: on
line diff
--- a/src/main/java/org/icedrobot/daneel/dex/dexlib/DexLibDexReader.java Sat Mar 19 10:18:40 2011 +0100 +++ b/src/main/java/org/icedrobot/daneel/dex/dexlib/DexLibDexReader.java Sat Mar 19 15:37:50 2011 +0100 @@ -39,6 +39,7 @@ import java.io.File; import java.io.IOException; +import java.lang.reflect.Field; import java.util.HashMap; import java.util.List; @@ -48,6 +49,7 @@ import org.icedrobot.daneel.dex.DexMethodVisitor; import org.icedrobot.daneel.dex.DexReader; import org.icedrobot.daneel.dex.Opcode; +import org.icedrobot.daneel.rewriter.Registers; import org.jf.dexlib.ClassDataItem; import org.jf.dexlib.ClassDataItem.EncodedField; import org.jf.dexlib.ClassDataItem.EncodedMethod; @@ -235,14 +237,39 @@ // visit attribute - mv.visitCode(codeItem.getRegisterCount(), -1, -1); // FIXME - // insSize/outSize + int inWords, outWords; + try { + inWords = IN_WORDS.getInt(codeItem); + outWords = OUT_WORDS.getInt(codeItem); + } catch (IllegalArgumentException e) { + throw (AssertionError) new AssertionError().initCause(e); + } catch (IllegalAccessException e) { + throw (AssertionError) new AssertionError().initCause(e); + } + + mv.visitCode(codeItem.getRegisterCount(), inWords, outWords); acceptCode(codeItem, mv); mv.visitEnd(); } } } + private static final Field IN_WORDS; + private static final Field OUT_WORDS; + static { + Field inWords, outWords; + try { + inWords = CodeItem.class.getDeclaredField("inWords"); + outWords = CodeItem.class.getDeclaredField("outWords"); + } catch (NoSuchFieldException e) { + throw (AssertionError) new AssertionError().initCause(e); + } + inWords.setAccessible(true); + outWords.setAccessible(true); + IN_WORDS = inWords; + OUT_WORDS = outWords; + } + private static String[] asDescriptorArray(ProtoIdItem protoIdItem) { TypeListItem parameters = protoIdItem.getParameters(); if (parameters == null) { @@ -358,17 +385,18 @@ case INSTR_METHOD: { int va, vpacked, size; - if (instr instanceof RegisterRangeInstruction) { // range - RegisterRangeInstruction rangeInstr = (RegisterRangeInstruction)instr; - size = rangeInstr.getRegCount(); - va = rangeInstr.getStartRegister(); - vpacked = 0; + 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(); + FiveRegisterInstruction fiveInstr = (FiveRegisterInstruction) instr; + size = fiveInstr.getRegCount(); + va = fiveInstr.getRegisterA(); + vpacked = Registers.packRegisters(fiveInstr.getRegisterD(), + fiveInstr.getRegisterE(), fiveInstr.getRegisterF(), + fiveInstr.getRegisterG()); } InstructionWithReference refInstr = (InstructionWithReference) instr; MethodIdItem methodIdItem = (MethodIdItem) refInstr.getReferencedItem();
--- a/src/main/java/org/icedrobot/daneel/rewriter/DexRewriter.java Sat Mar 19 10:18:40 2011 +0100 +++ b/src/main/java/org/icedrobot/daneel/rewriter/DexRewriter.java Sat Mar 19 15:37:50 2011 +0100 @@ -140,11 +140,27 @@ private Interpreter interpreter; private int returnRegisterType; // type of the register used to stored // the return value + private int locals; // number of local variables + private int parameters; // number of parameters public MethodRewriter(MethodVisitor mv) { this.mv = new PatchMethodVisitor(mv); } + /** + * Translate a register with Dalvik calling convention to a slot with + * Java calling convention + * + * @param register the register + * @return the corresponding Java slot. + */ + private int registerToSlot(int register) { + if (register >= locals) { // it's a parameter + return register - locals; + } // otherwise it's a local variable + return parameters + register; + } + private static int getTypeFromASMType(Type type) { switch (type.getSort()) { case Type.BOOLEAN: @@ -185,6 +201,8 @@ @Override public void visitCode(int registerSize, int insSize, int outSize) { mv.visitCode(); + this.locals = registerSize - insSize; + this.parameters = insSize; interpreter = new Interpreter(registerSize); } @@ -205,6 +223,8 @@ @Override public void visitInstrField(Opcode opcode, int vsrcOrDest, int vref, String owner, String name, String desc) { + vsrcOrDest = registerToSlot(vsrcOrDest); + vref = registerToSlot(vref); owner = TypeUtil.convertDescToInternal(owner); if (opcode.compareTo(Opcode.IGET) >= 0 && opcode.compareTo(Opcode.IGET_SHORT) <= 0) { @@ -241,6 +261,7 @@ @Override public void visitInstrConstString(Opcode opcode, int vdest, String value) { + vdest = registerToSlot(vdest); mv.visitLdcInsn(value); mv.visitVarInsn(ASTORE, vdest); interpreter.store(vdest, OBJECT_TYPE); @@ -289,7 +310,8 @@ int r; if (erasedRangeOpcode != Opcode.INVOKE_STATIC) { r = 1; - int register = (registers == null) ? va : registers[0]; + int register = registerToSlot((registers == null) ? va + : registers[0]); mv.visitVarInsn(ALOAD, register); interpreter.load(register, OBJECT_TYPE); } else { @@ -299,7 +321,8 @@ Type[] types = Type.getArgumentTypes(desc); for (Type asmType : types) { int type = getTypeFromASMType(asmType); - int register = (registers == null) ? va + r : registers[r]; + int register = registerToSlot((registers == null) ? va + r + : registers[r]); mv.visitVarInsn(Register.getJavaOpcode(type, ILOAD), register); interpreter.load(register, type); r += asmType.getSize(); @@ -316,40 +339,42 @@ Opcode.INVOKE_VIRTUAL.ordinal(); @Override - public void visitInstrConstU32(Opcode opcode, final int vdest, + public void visitInstrConstU32(Opcode opcode, int vdest, final int value) { + final int sdest = registerToSlot(vdest); mv.setPatchMode(); mv.visitLdcInsn(value); final AbstractInsnNode ldc = mv.getLastInsnNode(); - mv.visitVarInsn(ISTORE, vdest); + mv.visitVarInsn(ISTORE, sdest); final AbstractInsnNode istore = mv.getLastInsnNode(); - interpreter.storeArbitraryType(vdest, U32_TYPE, new Patchable() { + interpreter.storeArbitraryType(sdest, 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.patch(istore, new VarInsnNode(FSTORE, sdest)); } } }); } @Override - public void visitInstrConstU64(Opcode opcode, final int vdest, + public void visitInstrConstU64(Opcode opcode, int vdest, final long value) { + final int sdest = registerToSlot(vdest); mv.setPatchMode(); mv.visitLdcInsn(value); final AbstractInsnNode ldc = mv.getLastInsnNode(); - mv.visitVarInsn(LSTORE, vdest); + mv.visitVarInsn(LSTORE, sdest); final AbstractInsnNode lstore = mv.getLastInsnNode(); - interpreter.storeArbitraryType(vdest, U64_TYPE, new Patchable() { + interpreter.storeArbitraryType(sdest, U64_TYPE, new Patchable() { @Override protected void patch(int registerType) { if (registerType == DOUBLE_TYPE) { mv.patch(ldc, new LdcInsnNode(Double.longBitsToDouble(value))); - mv.patch(lstore, new VarInsnNode(DSTORE, vdest)); + mv.patch(lstore, new VarInsnNode(DSTORE, sdest)); } } }); @@ -364,35 +389,44 @@ @Override public void visitInstrArray(Opcode opcode, int vsrcOrDest, int varray, int vindex) { + vsrcOrDest = registerToSlot(vsrcOrDest); throw new UnsupportedOperationException("NYI " + opcode); } @Override public void visitInstrBinOp(Opcode opcode, int vdest, int vsrc, int vsrc2) { + vdest = registerToSlot(vdest); + vsrc = registerToSlot(vsrc); + vsrc2 = registerToSlot(vsrc2); throw new UnsupportedOperationException("NYI " + opcode); } @Override public void visitInstrBinOpAndLiteral(Opcode opcode, int vdest, int vsrc, int value) { + vdest = registerToSlot(vdest); + vsrc = registerToSlot(vsrc); throw new UnsupportedOperationException("NYI " + opcode); } @Override public void visitInstrClass(Opcode opcode, int vdest, String type) { + vdest = registerToSlot(vdest); throw new UnsupportedOperationException("NYI " + opcode); } @Override public void visitInstrFillArrayData(Opcode opcode, int vsrc, Object arrayData) { + vsrc = registerToSlot(vsrc); throw new UnsupportedOperationException("NYI " + opcode); } @Override public void visitInstrFilledNewArray(Opcode opcode, int num, int va, int vpacked, String type) { + // don't forget to use registerToSlot throw new UnsupportedOperationException("NYI " + opcode); } @@ -404,39 +438,49 @@ @Override public void visitInstrIfTest(Opcode opcode, int vsrc1, int vsrc2, Label label) { + vsrc1 = registerToSlot(vsrc1); + vsrc2 = registerToSlot(vsrc2); throw new UnsupportedOperationException("NYI " + opcode); } @Override public void visitInstrIfTestZ(Opcode opcode, int vsrc, Label label) { + vsrc = registerToSlot(vsrc); throw new UnsupportedOperationException("NYI " + opcode); } @Override public void visitInstrInstanceof(Opcode opcode, int vdest, int vsrc, String type) { + vdest = registerToSlot(vdest); + vsrc = registerToSlot(vsrc); throw new UnsupportedOperationException("NYI " + opcode); } @Override public void visitInstrNewArray(Opcode opcode, int vdest, int vsize, String type) { + vdest = registerToSlot(vdest); throw new UnsupportedOperationException("NYI " + opcode); } @Override public void visitInstrOp(Opcode opcode, int srcOrDst) { + srcOrDst = registerToSlot(srcOrDst); throw new UnsupportedOperationException("NYI " + opcode); } @Override public void visitInstrSwitch(Opcode opcode, int vsrc, Map<Integer, Label> labels) { + vsrc = registerToSlot(vsrc); throw new UnsupportedOperationException("NYI " + opcode); } @Override public void visitInstrUnaryOp(Opcode opcode, int vdest, int vsrc) { + vdest = registerToSlot(vdest); + vsrc = registerToSlot(vsrc); throw new UnsupportedOperationException("NYI " + opcode); }
--- a/src/main/java/org/icedrobot/daneel/rewriter/Registers.java Sat Mar 19 10:18:40 2011 +0100 +++ b/src/main/java/org/icedrobot/daneel/rewriter/Registers.java Sat Mar 19 15:37:50 2011 +0100 @@ -57,4 +57,8 @@ public static int getRegisterG(int packed) { return (packed >> 12) & 0x0F; } + + public static int packRegisters(int vd, int ve, int vf, int vg) { + return vg << 12 | vf << 8 | ve << 4 | vd; + } }