Fix modification of args array being ignored when calling "backup" method
This commit is contained in:
parent
f1c9b21ca7
commit
af4feada27
|
|
@ -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<TypeId, Local> tmpLocals, boolean castObj) {
|
||||||
String unboxMethod;
|
String unboxMethod;
|
||||||
TypeId typeId = target.getType();
|
TypeId typeId = target.getType();
|
||||||
TypeId<?> boxTypeId;
|
TypeId<?> boxTypeId;
|
||||||
if (typeId.equals(TypeId.BOOLEAN)) {
|
if (typeId.equals(TypeId.BOOLEAN)) {
|
||||||
unboxMethod = "booleanValue";
|
unboxMethod = "booleanValue";
|
||||||
boxTypeId = TypeId.get(Boolean.class);
|
boxTypeId = TypeId.get("Ljava/lang/Boolean;");
|
||||||
code.invokeVirtual(boxTypeId.getMethod(TypeId.BOOLEAN, unboxMethod), target, source);
|
Local boxTypedLocal = tmpLocals.get(boxTypeId);
|
||||||
|
code.cast(boxTypedLocal, source);
|
||||||
|
code.invokeVirtual(boxTypeId.getMethod(TypeId.BOOLEAN, unboxMethod), target, boxTypedLocal);
|
||||||
} else if (typeId.equals(TypeId.BYTE)) {
|
} else if (typeId.equals(TypeId.BYTE)) {
|
||||||
unboxMethod = "byteValue";
|
unboxMethod = "byteValue";
|
||||||
boxTypeId = TypeId.get(Byte.class);
|
boxTypeId = TypeId.get("Ljava/lang/Byte;");
|
||||||
code.invokeVirtual(boxTypeId.getMethod(TypeId.BYTE, unboxMethod), target, source);
|
Local boxTypedLocal = tmpLocals.get(boxTypeId);
|
||||||
|
code.cast(boxTypedLocal, source);
|
||||||
|
code.invokeVirtual(boxTypeId.getMethod(TypeId.BYTE, unboxMethod), target, boxTypedLocal);
|
||||||
} else if (typeId.equals(TypeId.CHAR)) {
|
} else if (typeId.equals(TypeId.CHAR)) {
|
||||||
unboxMethod = "charValue";
|
unboxMethod = "charValue";
|
||||||
boxTypeId = TypeId.get(Character.class);
|
boxTypeId = TypeId.get("Ljava/lang/Character;");
|
||||||
code.invokeVirtual(boxTypeId.getMethod(TypeId.CHAR, unboxMethod), target, source);
|
Local boxTypedLocal = tmpLocals.get(boxTypeId);
|
||||||
|
code.cast(boxTypedLocal, source);
|
||||||
|
code.invokeVirtual(boxTypeId.getMethod(TypeId.CHAR, unboxMethod), target, boxTypedLocal);
|
||||||
} else if (typeId.equals(TypeId.DOUBLE)) {
|
} else if (typeId.equals(TypeId.DOUBLE)) {
|
||||||
unboxMethod = "doubleValue";
|
unboxMethod = "doubleValue";
|
||||||
boxTypeId = TypeId.get(Double.class);
|
boxTypeId = TypeId.get("Ljava/lang/Double;");
|
||||||
code.invokeVirtual(boxTypeId.getMethod(TypeId.DOUBLE, unboxMethod), target, source);
|
Local boxTypedLocal = tmpLocals.get(boxTypeId);
|
||||||
|
code.cast(boxTypedLocal, source);
|
||||||
|
code.invokeVirtual(boxTypeId.getMethod(TypeId.DOUBLE, unboxMethod), target, boxTypedLocal);
|
||||||
} else if (typeId.equals(TypeId.FLOAT)) {
|
} else if (typeId.equals(TypeId.FLOAT)) {
|
||||||
unboxMethod = "floatValue";
|
unboxMethod = "floatValue";
|
||||||
boxTypeId = TypeId.get(Float.class);
|
boxTypeId = TypeId.get("Ljava/lang/Float;");
|
||||||
code.invokeVirtual(boxTypeId.getMethod(TypeId.FLOAT, unboxMethod), target, source);
|
Local boxTypedLocal = tmpLocals.get(boxTypeId);
|
||||||
|
code.cast(boxTypedLocal, source);
|
||||||
|
code.invokeVirtual(boxTypeId.getMethod(TypeId.FLOAT, unboxMethod), target, boxTypedLocal);
|
||||||
} else if (typeId.equals(TypeId.INT)) {
|
} else if (typeId.equals(TypeId.INT)) {
|
||||||
unboxMethod = "intValue";
|
unboxMethod = "intValue";
|
||||||
boxTypeId = TypeId.get(Integer.class);
|
boxTypeId = TypeId.get("Ljava/lang/Integer;");
|
||||||
code.invokeVirtual(boxTypeId.getMethod(TypeId.INT, unboxMethod), target, source);
|
Local boxTypedLocal = tmpLocals.get(boxTypeId);
|
||||||
|
code.cast(boxTypedLocal, source);
|
||||||
|
code.invokeVirtual(boxTypeId.getMethod(TypeId.INT, unboxMethod), target, boxTypedLocal);
|
||||||
} else if (typeId.equals(TypeId.LONG)) {
|
} else if (typeId.equals(TypeId.LONG)) {
|
||||||
unboxMethod = "longValue";
|
unboxMethod = "longValue";
|
||||||
boxTypeId = TypeId.get(Long.class);
|
boxTypeId = TypeId.get("Ljava/lang/Long;");
|
||||||
code.invokeVirtual(boxTypeId.getMethod(TypeId.LONG, unboxMethod), target, source);
|
Local boxTypedLocal = tmpLocals.get(boxTypeId);
|
||||||
|
code.cast(boxTypedLocal, source);
|
||||||
|
code.invokeVirtual(boxTypeId.getMethod(TypeId.LONG, unboxMethod), target, boxTypedLocal);
|
||||||
} else if (typeId.equals(TypeId.SHORT)) {
|
} else if (typeId.equals(TypeId.SHORT)) {
|
||||||
unboxMethod = "shortValue";
|
unboxMethod = "shortValue";
|
||||||
boxTypeId = TypeId.get(Short.class);
|
boxTypeId = TypeId.get("Ljava/lang/Short;");
|
||||||
code.invokeVirtual(boxTypeId.getMethod(TypeId.SHORT, unboxMethod), target, source);
|
Local boxTypedLocal = tmpLocals.get(boxTypeId);
|
||||||
|
code.cast(boxTypedLocal, source);
|
||||||
|
code.invokeVirtual(boxTypeId.getMethod(TypeId.SHORT, unboxMethod), target, boxTypedLocal);
|
||||||
} else if (typeId.equals(TypeId.VOID)) {
|
} else if (typeId.equals(TypeId.VOID)) {
|
||||||
code.loadConstant(target, null);
|
code.loadConstant(target, null);
|
||||||
|
} else if (castObj){
|
||||||
|
code.cast(target, source);
|
||||||
} else {
|
} else {
|
||||||
code.move(target, source);
|
code.move(target, source);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -311,7 +311,7 @@ public class HookerDexMaker {
|
||||||
Local<Object> callbackObj = code.newLocal(TypeId.OBJECT);
|
Local<Object> callbackObj = code.newLocal(TypeId.OBJECT);
|
||||||
Local<XC_MethodHook> callback = code.newLocal(callbackTypeId);
|
Local<XC_MethodHook> callback = code.newLocal(callbackTypeId);
|
||||||
|
|
||||||
Local<Object> resultObj = code.newLocal(TypeId.OBJECT);
|
Local<Object> resultObj = code.newLocal(TypeId.OBJECT); // as a temp Local
|
||||||
Local<Integer> one = code.newLocal(TypeId.INT);
|
Local<Integer> one = code.newLocal(TypeId.INT);
|
||||||
Local<Object> nullObj = code.newLocal(TypeId.OBJECT);
|
Local<Object> nullObj = code.newLocal(TypeId.OBJECT);
|
||||||
Local<Throwable> throwable = code.newLocal(throwableTypeId);
|
Local<Throwable> throwable = code.newLocal(throwableTypeId);
|
||||||
|
|
@ -435,6 +435,15 @@ public class HookerDexMaker {
|
||||||
// try to call backup
|
// try to call backup
|
||||||
// try start
|
// try start
|
||||||
code.addCatchClause(throwableTypeId, tryOrigCatch);
|
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
|
// get pre-created Local with a matching typeId
|
||||||
if (mReturnTypeId.equals(TypeId.VOID)) {
|
if (mReturnTypeId.equals(TypeId.VOID)) {
|
||||||
code.invokeStatic(mBackupMethodId, null, allArgsLocals);
|
code.invokeStatic(mBackupMethodId, null, allArgsLocals);
|
||||||
|
|
@ -511,7 +520,7 @@ public class HookerDexMaker {
|
||||||
code.cast(matchObjLocal, resultObj);
|
code.cast(matchObjLocal, resultObj);
|
||||||
// have to use matching typed Object(Integer, Double ...) to do unboxing
|
// have to use matching typed Object(Integer, Double ...) to do unboxing
|
||||||
Local toReturn = resultLocals.get(mReturnTypeId);
|
Local toReturn = resultLocals.get(mReturnTypeId);
|
||||||
autoUnboxIfNecessary(code, toReturn, matchObjLocal);
|
autoUnboxIfNecessary(code, toReturn, matchObjLocal, resultLocals, true);
|
||||||
// return
|
// return
|
||||||
code.returnValue(toReturn);
|
code.returnValue(toReturn);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue