diff --git a/Bridge/src/main/java/com/elderdrivers/riru/xposed/dexmaker/DexMakerUtils.java b/Bridge/src/main/java/com/elderdrivers/riru/xposed/dexmaker/DexMakerUtils.java index 94374a98..bb378cb8 100644 --- a/Bridge/src/main/java/com/elderdrivers/riru/xposed/dexmaker/DexMakerUtils.java +++ b/Bridge/src/main/java/com/elderdrivers/riru/xposed/dexmaker/DexMakerUtils.java @@ -44,44 +44,63 @@ public class DexMakerUtils { } } - public static void autoUnboxIfNecessary(Code code, Local target, Local source) { + public static void autoUnboxIfNecessary(Code code, Local target, Local source, + Map tmpLocals, boolean castObj) { String unboxMethod; TypeId typeId = target.getType(); TypeId boxTypeId; if (typeId.equals(TypeId.BOOLEAN)) { unboxMethod = "booleanValue"; - boxTypeId = TypeId.get(Boolean.class); - code.invokeVirtual(boxTypeId.getMethod(TypeId.BOOLEAN, unboxMethod), target, source); + boxTypeId = TypeId.get("Ljava/lang/Boolean;"); + Local boxTypedLocal = tmpLocals.get(boxTypeId); + code.cast(boxTypedLocal, source); + code.invokeVirtual(boxTypeId.getMethod(TypeId.BOOLEAN, unboxMethod), target, boxTypedLocal); } else if (typeId.equals(TypeId.BYTE)) { unboxMethod = "byteValue"; - boxTypeId = TypeId.get(Byte.class); - code.invokeVirtual(boxTypeId.getMethod(TypeId.BYTE, unboxMethod), target, source); + boxTypeId = TypeId.get("Ljava/lang/Byte;"); + Local boxTypedLocal = tmpLocals.get(boxTypeId); + code.cast(boxTypedLocal, source); + code.invokeVirtual(boxTypeId.getMethod(TypeId.BYTE, unboxMethod), target, boxTypedLocal); } else if (typeId.equals(TypeId.CHAR)) { unboxMethod = "charValue"; - boxTypeId = TypeId.get(Character.class); - code.invokeVirtual(boxTypeId.getMethod(TypeId.CHAR, unboxMethod), target, source); + boxTypeId = TypeId.get("Ljava/lang/Character;"); + Local boxTypedLocal = tmpLocals.get(boxTypeId); + code.cast(boxTypedLocal, source); + code.invokeVirtual(boxTypeId.getMethod(TypeId.CHAR, unboxMethod), target, boxTypedLocal); } else if (typeId.equals(TypeId.DOUBLE)) { unboxMethod = "doubleValue"; - boxTypeId = TypeId.get(Double.class); - code.invokeVirtual(boxTypeId.getMethod(TypeId.DOUBLE, unboxMethod), target, source); + boxTypeId = TypeId.get("Ljava/lang/Double;"); + Local boxTypedLocal = tmpLocals.get(boxTypeId); + code.cast(boxTypedLocal, source); + code.invokeVirtual(boxTypeId.getMethod(TypeId.DOUBLE, unboxMethod), target, boxTypedLocal); } else if (typeId.equals(TypeId.FLOAT)) { unboxMethod = "floatValue"; - boxTypeId = TypeId.get(Float.class); - code.invokeVirtual(boxTypeId.getMethod(TypeId.FLOAT, unboxMethod), target, source); + boxTypeId = TypeId.get("Ljava/lang/Float;"); + Local boxTypedLocal = tmpLocals.get(boxTypeId); + code.cast(boxTypedLocal, source); + code.invokeVirtual(boxTypeId.getMethod(TypeId.FLOAT, unboxMethod), target, boxTypedLocal); } else if (typeId.equals(TypeId.INT)) { unboxMethod = "intValue"; - boxTypeId = TypeId.get(Integer.class); - code.invokeVirtual(boxTypeId.getMethod(TypeId.INT, unboxMethod), target, source); + boxTypeId = TypeId.get("Ljava/lang/Integer;"); + Local boxTypedLocal = tmpLocals.get(boxTypeId); + code.cast(boxTypedLocal, source); + code.invokeVirtual(boxTypeId.getMethod(TypeId.INT, unboxMethod), target, boxTypedLocal); } else if (typeId.equals(TypeId.LONG)) { unboxMethod = "longValue"; - boxTypeId = TypeId.get(Long.class); - code.invokeVirtual(boxTypeId.getMethod(TypeId.LONG, unboxMethod), target, source); + boxTypeId = TypeId.get("Ljava/lang/Long;"); + Local boxTypedLocal = tmpLocals.get(boxTypeId); + code.cast(boxTypedLocal, source); + code.invokeVirtual(boxTypeId.getMethod(TypeId.LONG, unboxMethod), target, boxTypedLocal); } else if (typeId.equals(TypeId.SHORT)) { unboxMethod = "shortValue"; - boxTypeId = TypeId.get(Short.class); - code.invokeVirtual(boxTypeId.getMethod(TypeId.SHORT, unboxMethod), target, source); + boxTypeId = TypeId.get("Ljava/lang/Short;"); + Local boxTypedLocal = tmpLocals.get(boxTypeId); + code.cast(boxTypedLocal, source); + code.invokeVirtual(boxTypeId.getMethod(TypeId.SHORT, unboxMethod), target, boxTypedLocal); } else if (typeId.equals(TypeId.VOID)) { code.loadConstant(target, null); + } else if (castObj){ + code.cast(target, source); } else { code.move(target, source); } diff --git a/Bridge/src/main/java/com/elderdrivers/riru/xposed/dexmaker/HookerDexMaker.java b/Bridge/src/main/java/com/elderdrivers/riru/xposed/dexmaker/HookerDexMaker.java index cab0665e..97d9aba3 100644 --- a/Bridge/src/main/java/com/elderdrivers/riru/xposed/dexmaker/HookerDexMaker.java +++ b/Bridge/src/main/java/com/elderdrivers/riru/xposed/dexmaker/HookerDexMaker.java @@ -311,7 +311,7 @@ public class HookerDexMaker { Local callbackObj = code.newLocal(TypeId.OBJECT); Local callback = code.newLocal(callbackTypeId); - Local resultObj = code.newLocal(TypeId.OBJECT); + Local resultObj = code.newLocal(TypeId.OBJECT); // as a temp Local Local one = code.newLocal(TypeId.INT); Local nullObj = code.newLocal(TypeId.OBJECT); Local throwable = code.newLocal(throwableTypeId); @@ -435,6 +435,15 @@ public class HookerDexMaker { // try to call backup // try start code.addCatchClause(throwableTypeId, tryOrigCatch); + // we have to load args[] to paramLocals + // because args[] may be changed in beforeHookedMethod + // should consider first param is thisObj if hooked method is not static + offset = mIsStatic ? 0 : 1; + for (int i = offset; i < allArgsLocals.length; i++) { + code.loadConstant(argIndex, i - offset); + code.aget(resultObj, args, argIndex); + autoUnboxIfNecessary(code, allArgsLocals[i], resultObj, resultLocals, true); + } // get pre-created Local with a matching typeId if (mReturnTypeId.equals(TypeId.VOID)) { code.invokeStatic(mBackupMethodId, null, allArgsLocals); @@ -511,7 +520,7 @@ public class HookerDexMaker { code.cast(matchObjLocal, resultObj); // have to use matching typed Object(Integer, Double ...) to do unboxing Local toReturn = resultLocals.get(mReturnTypeId); - autoUnboxIfNecessary(code, toReturn, matchObjLocal); + autoUnboxIfNecessary(code, toReturn, matchObjLocal, resultLocals, true); // return code.returnValue(toReturn); }