Skip to content

Commit

Permalink
Fix issues with J2IRConverter
Browse files Browse the repository at this point in the history
Fixes #28

# Conflicts:
#	dex-reader-api/src/main/java/com/googlecode/d2j/MethodHandle.java
#	dex-translator/src/main/java/com/googlecode/d2j/converter/J2IRConverter.java
  • Loading branch information
ThexXTURBOXx authored and pxb1988 committed Aug 31, 2023
1 parent ef29be1 commit b6f242c
Show file tree
Hide file tree
Showing 7 changed files with 150 additions and 61 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package com.googlecode.dex2jar.ir.expr;

import com.googlecode.d2j.CallSite;
import com.googlecode.d2j.DexType;
import com.googlecode.d2j.Method;
import com.googlecode.d2j.MethodHandle;
Expand Down Expand Up @@ -200,8 +201,8 @@ public static InvokeExpr nInvokeVirtual(Value[] regs, String owner, String name,
return new InvokeExpr(VT.INVOKE_VIRTUAL, regs, owner, name, argmentTypes, returnType);
}

public static InvokeCustomExpr nInvokeCustom(Value[] regs, String name, Proto proto, MethodHandle handle, Object[] bsmArgs) {
return new InvokeCustomExpr(VT.INVOKE_CUSTOM, regs , name, proto, handle, bsmArgs);
public static InvokeCustomExpr nInvokeCustom(Value[] regs, CallSite callSite) {
return new InvokeCustomExpr(VT.INVOKE_CUSTOM, regs , callSite);
}

public static InvokePolymorphicExpr nInvokePolymorphic(Value[] regs, Proto proto, Method method) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,46 +15,37 @@
*/
package com.googlecode.dex2jar.ir.expr;

import com.googlecode.d2j.MethodHandle;
import com.googlecode.d2j.CallSite;
import com.googlecode.d2j.Proto;
import com.googlecode.dex2jar.ir.LabelAndLocalMapper;

public class InvokeCustomExpr extends AbstractInvokeExpr {
public String name;
public Proto proto;
public MethodHandle handle;
public Object[] bsmArgs;
public CallSite callSite;

@Override
protected void releaseMemory() {
name = null;
proto = null;
handle = null;
bsmArgs = null;
callSite = null;
super.releaseMemory();
}

@Override
public Proto getProto() {
return proto;
return callSite.getMethodProto();
}

public InvokeCustomExpr(VT type, Value[] args, String methodName, Proto proto, MethodHandle handle, Object[] bsmArgs) {
public InvokeCustomExpr(VT type, Value[] args, CallSite callSite) {
super(type, args);
this.proto = proto;
this.name = methodName;
this.handle = handle;
this.bsmArgs = bsmArgs;
this.callSite = callSite;
}

@Override
public Value clone() {
return new InvokeCustomExpr(vt, cloneOps(), name, proto, handle, bsmArgs);
return new InvokeCustomExpr(vt, cloneOps(), callSite);
}

@Override
public Value clone(LabelAndLocalMapper mapper) {
return new InvokeCustomExpr(vt, cloneOps(mapper), name, proto, handle, bsmArgs);
return new InvokeCustomExpr(vt, cloneOps(mapper), callSite);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1135,11 +1135,7 @@ public DvmValue naryOperation(DexStmtNode insn, List<? extends DvmValue> values)
vs[i] = getLocal(values.get(i));
}
MethodCustomStmtNode n = (MethodCustomStmtNode) insn;
Value invoke = nInvokeCustom(vs,
n.callSite.getMethodName(),
n.callSite.getMethodProto(),
n.callSite.getBootstrapMethodHandler(),
n.callSite.getExtraArguments());
Value invoke = nInvokeCustom(vs, n.callSite);
if ("V".equals(n.getProto().getReturnType())) {
emit(nVoidInvoke(invoke));
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*/
package com.googlecode.d2j.converter;

import com.googlecode.d2j.CallSite;
import com.googlecode.d2j.DexType;
import com.googlecode.d2j.Method;
import com.googlecode.d2j.MethodHandle;
Expand Down Expand Up @@ -839,7 +840,10 @@ && isConstant(fae.ops)) {
} else {
throw new RuntimeException();
}
asm.visitInvokeDynamicInsn(ice.name, ice.proto.getDesc(), (Handle) Dex2Asm.convertConstantValue(ice.handle), Dex2Asm.convertConstantValues(ice.bsmArgs));
CallSite callSite = ice.callSite;
asm.visitInvokeDynamicInsn(callSite.getMethodName(), callSite.getMethodProto().getDesc(),
Dex2Asm.convertHandler(callSite.getBootstrapMethodHandler()),
Dex2Asm.convertConstantValues(callSite.getExtraArguments()));
}
break;
case INVOKE_POLYMORPHIC: {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
package com.googlecode.d2j.converter;

import com.googlecode.d2j.CallSite;
import com.googlecode.d2j.MethodHandle;
import com.googlecode.d2j.Proto;
import com.googlecode.d2j.dex.Asm2Dex;
import com.googlecode.dex2jar.ir.IrMethod;
import com.googlecode.dex2jar.ir.Trap;
import com.googlecode.dex2jar.ir.expr.Exprs;
import com.googlecode.dex2jar.ir.expr.InvokeCustomExpr;
import com.googlecode.dex2jar.ir.expr.Local;
import com.googlecode.dex2jar.ir.expr.NewMutiArrayExpr;
import com.googlecode.dex2jar.ir.stmt.*;

import org.objectweb.asm.Handle;
Expand Down Expand Up @@ -517,7 +523,7 @@ public JvmValue unaryOperation(AbstractInsnNode insn, JvmValue value0) throws An
case T_DOUBLE:
return b(1, Exprs.nNewArray("D", local));
case T_LONG:
return b(1, Exprs.nNewArray("D", local));
return b(1, Exprs.nNewArray("J", local));
default:
throw new AnalyzerException(insn, "Invalid array type");
}
Expand Down Expand Up @@ -764,7 +770,16 @@ public JvmValue naryOperation(AbstractInsnNode insn, List<? extends JvmValue> xv
values[i] = getLocal(xvalues.get(i));
}
if (insn.getOpcode() == MULTIANEWARRAY) {
throw new UnsupportedOperationException("Not supported yet.");
MultiANewArrayInsnNode multi = (MultiANewArrayInsnNode) insn;
NewMutiArrayExpr n = Exprs.nNewMutiArray(multi.desc.replaceAll("\\[+", ""), multi.dims, values);
return b(Type.getType(multi.desc).getSize(), n);
} else if (insn.getOpcode() == INVOKEDYNAMIC) {
InvokeDynamicInsnNode mi = (InvokeDynamicInsnNode) insn;
MethodHandle methodHandle = Asm2Dex.toMethodHandle(mi.bsm);
Proto methodType = Asm2Dex.toMethodType(mi.desc);
Object[] extraObjects = Asm2Dex.convertConstObjects(mi.bsmArgs);
InvokeCustomExpr d = Exprs.nInvokeCustom(values, new CallSite(null, methodHandle, mi.name, methodType, extraObjects));
return b(Type.getReturnType(mi.desc).getSize(), d);
} else {
MethodInsnNode mi = (MethodInsnNode) insn;
com.googlecode.dex2jar.ir.expr.Value v = null;
Expand All @@ -784,8 +799,6 @@ public JvmValue naryOperation(AbstractInsnNode insn, List<? extends JvmValue> xv
case INVOKEINTERFACE:
v = Exprs.nInvokeInterface(values, owner, mi.name, ps, ret);
break;
case INVOKEDYNAMIC:
throw new UnsupportedOperationException("Not supported yet.");
}
if ("V".equals(ret)) {
emit(Stmts.nVoidInvoke(v));
Expand Down
78 changes: 78 additions & 0 deletions dex-translator/src/main/java/com/googlecode/d2j/dex/Asm2Dex.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package com.googlecode.d2j.dex;

import com.googlecode.d2j.DexType;
import com.googlecode.d2j.Field;
import com.googlecode.d2j.Method;
import com.googlecode.d2j.MethodHandle;
import com.googlecode.d2j.Proto;

import org.objectweb.asm.Handle;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;

import java.util.Arrays;

public class Asm2Dex {
public static Object convertConstantValue(Object ele) {
if (ele instanceof Type) {
Type type = (Type) ele;
if (type.getSort() == Type.METHOD) {
return new Proto(toDescArray(type.getArgumentTypes()), type.getReturnType().getDescriptor());
}
return new DexType(type.getDescriptor());
} else if (ele instanceof Handle) {
return toMethodHandle((Handle) ele);
}
return ele;
}

public static Object[] convertConstObjects(Object[] bsmArgs) {
if (bsmArgs == null) {
return null;
}
Object[] copy = Arrays.copyOf(bsmArgs, bsmArgs.length);
for (int i = 0; i < copy.length; i++) {
Object ele = copy[i];
ele = convertConstantValue(ele);
copy[i] = ele;
}
return copy;
}

public static Proto toMethodType(String desc) {
return new Proto(toDescArray(Type.getArgumentTypes(desc)), Type.getReturnType(desc).getDescriptor());
}

public static MethodHandle toMethodHandle(Handle bsm) {
switch (bsm.getTag()) {
case Opcodes.H_GETFIELD:
return new MethodHandle(MethodHandle.INSTANCE_GET, toField(bsm.getOwner(), bsm.getName(), bsm.getDesc()));
case Opcodes.H_GETSTATIC:
return new MethodHandle(MethodHandle.STATIC_GET, toField(bsm.getOwner(), bsm.getName(), bsm.getDesc()));
case Opcodes.H_PUTFIELD:
return new MethodHandle(MethodHandle.INSTANCE_PUT, toField(bsm.getOwner(), bsm.getName(), bsm.getDesc()));
case Opcodes.H_PUTSTATIC:
return new MethodHandle(MethodHandle.STATIC_PUT, toField(bsm.getOwner(), bsm.getName(), bsm.getDesc()));
case Opcodes.H_INVOKEVIRTUAL:
return new MethodHandle(MethodHandle.INVOKE_INSTANCE, toMethod(bsm.getOwner(), bsm.getName(), bsm.getDesc()));
case Opcodes.H_INVOKESTATIC:
return new MethodHandle(MethodHandle.INVOKE_STATIC, toMethod(bsm.getOwner(), bsm.getName(), bsm.getDesc()));
case Opcodes.H_INVOKESPECIAL:
return new MethodHandle(MethodHandle.INVOKE_DIRECT, toMethod(bsm.getOwner(), bsm.getName(), bsm.getDesc()));
case Opcodes.H_NEWINVOKESPECIAL:
return new MethodHandle(MethodHandle.INVOKE_CONSTRUCTOR, toMethod(bsm.getOwner(), bsm.getName(), bsm.getDesc()));
case Opcodes.H_INVOKEINTERFACE:
return new MethodHandle(MethodHandle.INVOKE_INTERFACE, toMethod(bsm.getOwner(), bsm.getName(), bsm.getDesc()));
default:
throw new RuntimeException("Not supported yet.");
}
}

static private Method toMethod(String internalName, String name, String desc) {
return new Method("L" + internalName + ";", name, toMethodType(desc));
}

static private Field toField(String internalName, String name, String desc) {
return new Field("L" + internalName + ";", name, desc);
}
}
70 changes: 38 additions & 32 deletions dex-translator/src/main/java/com/googlecode/d2j/dex/Dex2Asm.java
Original file line number Diff line number Diff line change
Expand Up @@ -652,6 +652,9 @@ private static boolean isSignatureNotValid(String signature, boolean typeSignatu
}

public static Object[] convertConstantValues(Object[] v) {
if (v == null) {
return null;
}
Object[] copy = Arrays.copyOf(v, v.length);
for (int i = 0; i < copy.length; i++) {
Object ele = copy[i];
Expand All @@ -665,44 +668,47 @@ public static Object convertConstantValue(Object ele) {
if (ele instanceof DexType) {
ele = Type.getType(((DexType) ele).desc);
} else if (ele instanceof MethodHandle) {
Handle h = null;
MethodHandle mh = (MethodHandle) ele;
switch (mh.getType()) {
case MethodHandle.INSTANCE_GET:
h = new Handle(Opcodes.H_GETFIELD, toInternalName(mh.getField().getOwner()), mh.getField().getName(), mh.getField().getType(), false);
break;
case MethodHandle.INSTANCE_PUT:
h = new Handle(Opcodes.H_PUTFIELD, toInternalName(mh.getField().getOwner()), mh.getField().getName(), mh.getField().getType(), false);
break;
case MethodHandle.STATIC_GET:
h = new Handle(Opcodes.H_GETSTATIC, toInternalName(mh.getField().getOwner()), mh.getField().getName(), mh.getField().getType(), false);
break;
case MethodHandle.STATIC_PUT:
h = new Handle(Opcodes.H_PUTSTATIC, toInternalName(mh.getField().getOwner()), mh.getField().getName(), mh.getField().getType(), false);
break;
case MethodHandle.INVOKE_INSTANCE:
h = new Handle(Opcodes.H_INVOKEVIRTUAL, toInternalName(mh.getMethod().getOwner()), mh.getMethod().getName(), mh.getMethod().getDesc(), false);
break;
case MethodHandle.INVOKE_STATIC:
h = new Handle(Opcodes.H_INVOKESTATIC, toInternalName(mh.getMethod().getOwner()), mh.getMethod().getName(), mh.getMethod().getDesc(), false);
break;
case MethodHandle.INVOKE_CONSTRUCTOR:
h = new Handle(Opcodes.H_NEWINVOKESPECIAL, toInternalName(mh.getMethod().getOwner()), mh.getMethod().getName(), mh.getMethod().getDesc(), false);
break;
case MethodHandle.INVOKE_DIRECT:
h = new Handle(Opcodes.H_INVOKESPECIAL, toInternalName(mh.getMethod().getOwner()), mh.getMethod().getName(), mh.getMethod().getDesc(), false);
break;
case MethodHandle.INVOKE_INTERFACE:
h = new Handle(Opcodes.H_INVOKEINTERFACE, toInternalName(mh.getMethod().getOwner()), mh.getMethod().getName(), mh.getMethod().getDesc(), true);
break;
}
ele = h;
ele = convertHandler((MethodHandle) ele);
} else if (ele instanceof Proto) {
ele = Type.getMethodType(((Proto) ele).getDesc());
}
return ele;
}

public static Handle convertHandler(MethodHandle ele) {
Handle h = null;
switch (ele.getType()) {
case MethodHandle.INSTANCE_GET:
h = new Handle(Opcodes.H_GETFIELD, toInternalName(ele.getField().getOwner()), ele.getField().getName(), ele.getField().getType(), false);
break;
case MethodHandle.INSTANCE_PUT:
h = new Handle(Opcodes.H_PUTFIELD, toInternalName(ele.getField().getOwner()), ele.getField().getName(), ele.getField().getType(), false);
break;
case MethodHandle.STATIC_GET:
h = new Handle(Opcodes.H_GETSTATIC, toInternalName(ele.getField().getOwner()), ele.getField().getName(), ele.getField().getType(), false);
break;
case MethodHandle.STATIC_PUT:
h = new Handle(Opcodes.H_PUTSTATIC, toInternalName(ele.getField().getOwner()), ele.getField().getName(), ele.getField().getType(), false);
break;
case MethodHandle.INVOKE_INSTANCE:
h = new Handle(Opcodes.H_INVOKEVIRTUAL, toInternalName(ele.getMethod().getOwner()), ele.getMethod().getName(), ele.getMethod().getDesc(), false);
break;
case MethodHandle.INVOKE_STATIC:
h = new Handle(Opcodes.H_INVOKESTATIC, toInternalName(ele.getMethod().getOwner()), ele.getMethod().getName(), ele.getMethod().getDesc(), false);
break;
case MethodHandle.INVOKE_CONSTRUCTOR:
h = new Handle(Opcodes.H_NEWINVOKESPECIAL, toInternalName(ele.getMethod().getOwner()), ele.getMethod().getName(), ele.getMethod().getDesc(), false);
break;
case MethodHandle.INVOKE_DIRECT:
h = new Handle(Opcodes.H_INVOKESPECIAL, toInternalName(ele.getMethod().getOwner()), ele.getMethod().getName(), ele.getMethod().getDesc(), false);
break;
case MethodHandle.INVOKE_INTERFACE:
h = new Handle(Opcodes.H_INVOKEINTERFACE, toInternalName(ele.getMethod().getOwner()), ele.getMethod().getName(), ele.getMethod().getDesc(), true);
break;
}
return h;
}

public void convertMethod(DexClassNode classNode, DexMethodNode methodNode, ClassVisitor cv, ClzCtx clzCtx) {

MethodVisitor mv = collectBasicMethodInfo(methodNode, cv);
Expand Down

0 comments on commit b6f242c

Please sign in to comment.