Fix modification of args array being ignored when calling "backup" method

This commit is contained in:
solohsu 2019-01-21 23:55:52 +08:00
parent f1c9b21ca7
commit af4feada27
2 changed files with 47 additions and 19 deletions

View File

@ -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;
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);
}

View File

@ -311,7 +311,7 @@ public class HookerDexMaker {
Local<Object> callbackObj = code.newLocal(TypeId.OBJECT);
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<Object> nullObj = code.newLocal(TypeId.OBJECT);
Local<Throwable> 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);
}