Commit eb563c23 authored by swift_gan's avatar swift_gan Committed by swift_gan

tweak flow of call backup

parent 4825a173
......@@ -56,7 +56,7 @@ public class ActivityHooker {
static Method onCreateBackup;
@HookMethodBackup("onPause")
static Method onPauseBackup;
static HookWrapper.HookEntity onPauseBackup;
@HookMethod("onCreate")
@MethodParams(Bundle.class)
......@@ -68,7 +68,7 @@ public class ActivityHooker {
@HookMethod("onPause")
public static void onPause(@ThisObject Activity thiz) throws Throwable {
Log.e("ActivityHooker", "hooked onPause success " + thiz);
SandHook.callOriginByBackup(onPauseBackup, thiz);
onPauseBackup.callOrigin(thiz);
}
}
......
......@@ -10,6 +10,7 @@ import com.swift.sandhook.annotation.HookMethod;
import com.swift.sandhook.annotation.HookMethodBackup;
import com.swift.sandhook.annotation.MethodParams;
import com.swift.sandhook.annotation.ThisObject;
import com.swift.sandhook.wrapper.HookWrapper;
import java.lang.reflect.Method;
......@@ -21,7 +22,7 @@ public class ActivityHooker {
static Method onCreateBackup;
@HookMethodBackup("onPause")
static Method onPauseBackup;
static HookWrapper.HookEntity onPauseBackup;
@HookMethod("onCreate")
@MethodParams(Bundle.class)
......@@ -33,7 +34,7 @@ public class ActivityHooker {
@HookMethod("onPause")
public static void onPause(@ThisObject Activity thiz) throws Throwable {
Log.e("ActivityHooker", "hooked onPause success " + thiz);
SandHook.callOriginByBackup(onPauseBackup, thiz);
onPauseBackup.callOrigin(thiz);
}
}
......@@ -136,25 +136,25 @@ public class SandHook {
HookLog.d("method <" + entity.target.toString() + "> hook <" + (res == HookMode.INLINE ? "inline" : "replacement") + "> success!");
}
public static Object callOriginMethod(Member originMethod, Object thiz, Object... args) throws Throwable {
public final static Object callOriginMethod(Member originMethod, Object thiz, Object... args) throws Throwable {
HookWrapper.HookEntity hookEntity = globalHookEntityMap.get(originMethod);
if (hookEntity == null || hookEntity.backup == null)
return null;
return callOriginMethod(hookEntity.backupIsStub, originMethod, hookEntity.backup, thiz, args);
}
public static Object callOriginByBackup(Method backupMethod, Object thiz, Object... args) throws Throwable {
public final static Object callOriginByBackup(Method backupMethod, Object thiz, Object... args) throws Throwable {
HookWrapper.HookEntity hookEntity = globalBackupMap.get(backupMethod);
if (hookEntity == null)
return null;
return callOriginMethod(hookEntity.backupIsStub, hookEntity.target, backupMethod, thiz, args);
}
public static Object callOriginMethod(Member originMethod, Method backupMethod, Object thiz, Object[] args) throws Throwable {
public final static Object callOriginMethod(Member originMethod, Method backupMethod, Object thiz, Object[] args) throws Throwable {
return callOriginMethod(true, originMethod, backupMethod, thiz, args);
}
public static Object callOriginMethod(boolean backupIsStub, Member originMethod, Method backupMethod, Object thiz, Object[] args) throws Throwable {
public final static Object callOriginMethod(boolean backupIsStub, Member originMethod, Method backupMethod, Object thiz, Object[] args) throws Throwable {
//reset declaring class
if (!backupIsStub && SandHookConfig.SDK_INT >= Build.VERSION_CODES.N) {
//holder in stack to avoid moving gc
......@@ -184,7 +184,7 @@ public class SandHook {
}
}
public static void ensureBackupMethod(Method backupMethod) {
public final static void ensureBackupMethod(Method backupMethod) {
if (SandHookConfig.SDK_INT < Build.VERSION_CODES.N)
return;
HookWrapper.HookEntity entity = globalBackupMap.get(backupMethod);
......
......@@ -59,8 +59,6 @@ public class HookWrapper {
if (hookEntityMap.isEmpty())
return;
for (Field field:fields) {
if (!field.getType().equals(Method.class))
continue;
if (!Modifier.isStatic(field.getModifiers()))
continue;
HookMethodBackup hookMethodBackup = field.getAnnotation(HookMethodBackup.class);
......@@ -77,7 +75,11 @@ public class HookWrapper {
if (hookEntity.backup == null)
continue;
try {
field.set(null, hookEntity.backup);
if (field.getType() == Method.class) {
field.set(null, hookEntity.backup);
} else if (field.getType() == HookEntity.class) {
field.set(null, hookEntity);
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
......@@ -431,6 +433,10 @@ public class HookWrapper {
public boolean isCtor() {
return target instanceof Constructor;
}
public Object callOrigin(Object thiz, Object... args) throws Throwable {
return SandHook.callOriginMethod(backupIsStub, target, backup, thiz, args);
}
}
}
......@@ -40,6 +40,7 @@ public class HookStubManager {
public static Member[] originMethods;
public static HookMethodEntity[] hookMethodEntities;
public static XposedBridge.AdditionalHookInfo[] additionalHookInfos;
private static final Map<Member, XposedBridge.CopyOnWriteSortedSet<XC_MethodHook>> hookCallbacks
= sHookedMethodCallbacks;
......@@ -59,11 +60,12 @@ public class HookStubManager {
}
originMethods = new Member[ALL_STUB];
hookMethodEntities = new HookMethodEntity[ALL_STUB];
additionalHookInfos = new XposedBridge.AdditionalHookInfo[ALL_STUB];
}
}
public static HookMethodEntity getHookMethodEntity(Member origin) {
public static HookMethodEntity getHookMethodEntity(Member origin, XposedBridge.AdditionalHookInfo additionalHookInfo) {
if (!support()) {
return null;
......@@ -111,13 +113,14 @@ public class HookStubManager {
HookMethodEntity entity = new HookMethodEntity(origin, stubMethodInfo.hook, stubMethodInfo.backup);
entity.retType = retType;
entity.parType = parType;
int id = getMethodId(stubMethodInfo.args, stubMethodInfo.index);
originMethods[id] = origin;
hookMethodEntities[id] = entity;
if (hasStubBackup && !tryCompileAndResolveCallOriginMethod(entity.backup, stubMethodInfo.args, stubMethodInfo.index)) {
DexLog.w("internal stub <" + entity.hook.getName() + "> call origin compile failure, skip use internal stub");
return null;
} else {
int id = getMethodId(stubMethodInfo.args, stubMethodInfo.index);
originMethods[id] = origin;
hookMethodEntities[id] = entity;
additionalHookInfos[id] = additionalHookInfo;
return entity;
}
}
......@@ -257,7 +260,8 @@ public class HookStubManager {
DexLog.printMethodHookIn(originMethod);
Object[] snapshot = hookCallbacks.get(originMethod).getSnapshot();
Object[] snapshot = additionalHookInfos[id].callbacks.getSnapshot();
if (snapshot == null || snapshot.length == 0) {
if (hasStubBackup) {
return callOrigin.call(stubArgs);
......@@ -329,16 +333,17 @@ public class HookStubManager {
}
}
public static Object hookBridge(Member origin, Object thiz, Object... args) throws Throwable {
public static Object hookBridge(Member origin, Method backup, XposedBridge.AdditionalHookInfo additionalHookInfo, Object thiz, Object... args) throws Throwable {
if (XposedBridge.disableHooks) {
return SandHook.callOriginMethod(origin, thiz, args);
return SandHook.callOriginMethod(origin, backup, thiz, args);
}
DexLog.printMethodHookIn(origin);
Object[] snapshot = hookCallbacks.get(origin).getSnapshot();
Object[] snapshot = additionalHookInfo.callbacks.getSnapshot();
if (snapshot == null || snapshot.length == 0) {
return SandHook.callOriginMethod(origin, thiz, args);
}
......@@ -370,7 +375,7 @@ public class HookStubManager {
// call original method if not requested otherwise
if (!param.returnEarly) {
try {
param.setResult(SandHook.callOriginMethod(origin, thiz, param.args));
param.setResult(SandHook.callOriginMethod(origin, backup, thiz, param.args));
} catch (Throwable e) {
XposedBridge.log(e);
param.setThrowable(e);
......@@ -401,7 +406,7 @@ public class HookStubManager {
}
public final static long callOrigin(HookMethodEntity entity, Member origin, Object thiz, Object[] args) throws Throwable {
Object res = SandHook.callOriginMethod(origin, thiz, args);
Object res = SandHook.callOriginMethod(origin, entity.backup, thiz, args);
return entity.getResultAddress(res);
}
......
......@@ -60,7 +60,7 @@ public final class DynamicBridge {
long timeStart = System.currentTimeMillis();
HookMethodEntity stub = null;
if (XposedCompat.useInternalStub) {
stub = HookStubManager.getHookMethodEntity(hookMethod);
stub = HookStubManager.getHookMethodEntity(hookMethod, additionalHookInfo);
}
if (stub != null) {
SandHook.hook(new HookWrapper.HookEntity(hookMethod, stub.hook, stub.backup, false));
......
......@@ -34,7 +34,7 @@ public class HookerDexMakerNew implements HookMaker {
public static final String METHOD_NAME_HOOK = "hook";
public static final TypeId<Object[]> objArrayTypeId = TypeId.get(Object[].class);
private static final String CLASS_DESC_PREFIX = "L";
private static final String CLASS_NAME_PREFIX = "SandHookerN";
private static final String CLASS_NAME_PREFIX = "SandHookerNew";
private static final String FIELD_NAME_HOOK_INFO = "additionalHookInfo";
private static final String FIELD_NAME_METHOD = "method";
private static final String FIELD_NAME_BACKUP_METHOD = "backupMethod";
......@@ -228,12 +228,13 @@ public class HookerDexMakerNew implements HookMaker {
private void generateHookMethod() {
mHookMethodId = mHookerTypeId.getMethod(mReturnTypeId, METHOD_NAME_HOOK, mParameterTypeIds);
mSandHookBridgeMethodId = TypeId.get(HookStubManager.class).getMethod(TypeId.get(Object.class), "hookBridge", memberTypeId, TypeId.get(Object.class), TypeId.get(Object[].class));
mSandHookBridgeMethodId = TypeId.get(HookStubManager.class).getMethod(TypeId.get(Object.class), "hookBridge", memberTypeId, methodTypeId, hookInfoTypeId, TypeId.get(Object.class), TypeId.get(Object[].class));
Code code = mDexMaker.declare(mHookMethodId, Modifier.PUBLIC | Modifier.STATIC);
Local<Member> method = code.newLocal(memberTypeId);
// Local<Method> backupMethod = code.newLocal(methodTypeId);
Local<Member> originMethod = code.newLocal(memberTypeId);
Local<Method> backupMethod = code.newLocal(methodTypeId);
Local<XposedBridge.AdditionalHookInfo> hookInfo = code.newLocal(hookInfoTypeId);
Local<Object> thisObject = code.newLocal(TypeId.OBJECT);
Local<Object[]> args = code.newLocal(objArrayTypeId);
Local<Integer> actualParamSize = code.newLocal(TypeId.INT);
......@@ -244,10 +245,12 @@ public class HookerDexMakerNew implements HookMaker {
Map<TypeId, Local> resultLocals = createResultLocals(code);
code.sget(mMethodFieldId, method);
code.loadConstant(args, null);
code.loadConstant(argIndex, 0);
// code.sget(mBackupMethodFieldId, backupMethod);
code.sget(mMethodFieldId, originMethod);
code.sget(mBackupMethodFieldId, backupMethod);
code.sget(mHookInfoFieldId, hookInfo);
int paramsSize = mParameterTypeIds.length;
int offset = 0;
// thisObject
......@@ -273,10 +276,10 @@ public class HookerDexMakerNew implements HookMaker {
}
if (mReturnTypeId.equals(TypeId.VOID)) {
code.invokeStatic(mSandHookBridgeMethodId, null, method, thisObject, args);
code.invokeStatic(mSandHookBridgeMethodId, null, originMethod, backupMethod, hookInfo, thisObject, args);
code.returnVoid();
} else {
code.invokeStatic(mSandHookBridgeMethodId, resultObj, method, thisObject, args);
code.invokeStatic(mSandHookBridgeMethodId, resultObj, originMethod, backupMethod, hookInfo, thisObject, args);
TypeId objTypeId = getObjTypeIdIfPrimitive(mReturnTypeId);
Local matchObjLocal = resultLocals.get(objTypeId);
code.cast(matchObjLocal, resultObj);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment