Uniform the use of new ArtMethod resolution strategy
This commit is contained in:
parent
6b7c8e4942
commit
0336a2aa29
|
|
@ -122,7 +122,9 @@ public class HookMain {
|
||||||
checkCompatibleMethods(target, backup, "Original", "Backup");
|
checkCompatibleMethods(target, backup, "Original", "Backup");
|
||||||
}
|
}
|
||||||
if (backup != null) {
|
if (backup != null) {
|
||||||
HookMethodResolver.resolveMethod(hook, backup);
|
HookMethodResolver.resolveMethod(hook, backup, target);
|
||||||
|
} else {
|
||||||
|
Utils.logD("wanna resolve backup method, but it's null, target: " + target);
|
||||||
}
|
}
|
||||||
// make sure GC completed before hook
|
// make sure GC completed before hook
|
||||||
Thread currentThread = Thread.currentThread();
|
Thread currentThread = Thread.currentThread();
|
||||||
|
|
|
||||||
|
|
@ -91,22 +91,23 @@ public class HookMethodResolver {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void resolveMethod(Method hook, Method backup) {
|
public static void resolveMethod(Method hook, Method backup, Object target) {
|
||||||
if (canResolvedInJava && artMethodField != null) {
|
if (canResolvedInJava && artMethodField != null) {
|
||||||
// in java
|
// in java
|
||||||
try {
|
try {
|
||||||
resolveInJava(hook, backup);
|
resolveInJava(hook, backup, target);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// in native
|
// in native
|
||||||
resolveInNative(hook, backup);
|
resolveInNative(hook, backup, target);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// in native
|
// in native
|
||||||
resolveInNative(hook, backup);
|
resolveInNative(hook, backup, target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void resolveInJava(Method hook, Method backup) throws Exception {
|
private static void resolveInJava(Method hook, Method backup, Object target) throws Exception {
|
||||||
|
Utils.logD("start to resolve in java. target: " + target);
|
||||||
Object dexCache = dexCacheField.get(hook.getDeclaringClass());
|
Object dexCache = dexCacheField.get(hook.getDeclaringClass());
|
||||||
if (isArtMethod) {
|
if (isArtMethod) {
|
||||||
Object artMethod = artMethodField.get(backup);
|
Object artMethod = artMethodField.get(backup);
|
||||||
|
|
@ -121,7 +122,8 @@ public class HookMethodResolver {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void resolveInNative(Method hook, Method backup) {
|
private static void resolveInNative(Method hook, Method backup, Object target) {
|
||||||
|
Utils.logD("start to resolve in native. target: " + target);
|
||||||
Yahfa.ensureMethodCached(hook, backup);
|
Yahfa.ensureMethodCached(hook, backup);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,8 @@ void setNonCompilable(void *method);
|
||||||
|
|
||||||
bool setNativeFlag(void *method, bool isNative);
|
bool setNativeFlag(void *method, bool isNative);
|
||||||
|
|
||||||
|
void *getArtMethod(JNIEnv *env, jobject jmethod);
|
||||||
|
|
||||||
static void *getResolvedMethodsAddr(JNIEnv *, jobject);
|
static void *getResolvedMethodsAddr(JNIEnv *, jobject);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
||||||
|
|
@ -215,8 +215,8 @@ static int doBackupAndHook(JNIEnv *env, void *targetMethod, void *hookMethod, vo
|
||||||
|
|
||||||
static void ensureMethodCached(void *hookMethod, void *backupMethod,
|
static void ensureMethodCached(void *hookMethod, void *backupMethod,
|
||||||
void *hookClassResolvedMethods) {
|
void *hookClassResolvedMethods) {
|
||||||
if (!backupMethod || (long) backupMethod < 0x1000) {
|
if (!backupMethod) {
|
||||||
LOGW("ensureMethodCached: backupMethod is null or illegal: %p", backupMethod);
|
LOGE("ensureMethodCached: backupMethod is null");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
void *dexCacheResolvedMethods;
|
void *dexCacheResolvedMethods;
|
||||||
|
|
@ -263,7 +263,7 @@ static void ensureMethodCached(void *hookMethod, void *backupMethod,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *getArtMethod(JNIEnv *env, jobject jmethod) {
|
void *getArtMethod(JNIEnv *env, jobject jmethod) {
|
||||||
void *artMethod = NULL;
|
void *artMethod = NULL;
|
||||||
|
|
||||||
if (jmethod == NULL) {
|
if (jmethod == NULL) {
|
||||||
|
|
@ -272,8 +272,7 @@ static void *getArtMethod(JNIEnv *env, jobject jmethod) {
|
||||||
|
|
||||||
if (SDKVersion == __ANDROID_API_R__) {
|
if (SDKVersion == __ANDROID_API_R__) {
|
||||||
artMethod = (void *) (*env)->GetLongField(env, jmethod, fieldArtMethod);
|
artMethod = (void *) (*env)->GetLongField(env, jmethod, fieldArtMethod);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
artMethod = (void *) (*env)->FromReflectedMethod(env, jmethod);
|
artMethod = (void *) (*env)->FromReflectedMethod(env, jmethod);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -329,8 +328,8 @@ jboolean Java_lab_galaxy_yahfa_HookMain_backupAndHookNative(JNIEnv *env, jclass
|
||||||
void Java_lab_galaxy_yahfa_HookMain_ensureMethodCached(JNIEnv *env, jclass clazz,
|
void Java_lab_galaxy_yahfa_HookMain_ensureMethodCached(JNIEnv *env, jclass clazz,
|
||||||
jobject hook,
|
jobject hook,
|
||||||
jobject backup) {
|
jobject backup) {
|
||||||
ensureMethodCached((void *) (*env)->FromReflectedMethod(env, hook),
|
ensureMethodCached(getArtMethod(env, hook),
|
||||||
backup == NULL ? NULL : (void *) (*env)->FromReflectedMethod(env, backup),
|
getArtMethod(env, backup),
|
||||||
getResolvedMethodsAddr(env, hook));
|
getResolvedMethodsAddr(env, hook));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
#include <art/runtime/class_linker.h>
|
#include <art/runtime/class_linker.h>
|
||||||
#include <nativehelper/jni_macros.h>
|
#include <nativehelper/jni_macros.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <HookMain.h>
|
||||||
#include "art_class_linker.h"
|
#include "art_class_linker.h"
|
||||||
|
|
||||||
namespace edxp {
|
namespace edxp {
|
||||||
|
|
@ -11,7 +12,7 @@ namespace edxp {
|
||||||
static std::vector<void *> deopted_methods;
|
static std::vector<void *> deopted_methods;
|
||||||
|
|
||||||
static void ClassLinker_setEntryPointsToInterpreter(JNI_START, jobject method) {
|
static void ClassLinker_setEntryPointsToInterpreter(JNI_START, jobject method) {
|
||||||
void *reflected_method = env->FromReflectedMethod(method);
|
void *reflected_method = getArtMethod(env, method);
|
||||||
if (std::find(deopted_methods.begin(), deopted_methods.end(), reflected_method) !=
|
if (std::find(deopted_methods.begin(), deopted_methods.end(), reflected_method) !=
|
||||||
deopted_methods.end()) {
|
deopted_methods.end()) {
|
||||||
LOGD("method %p has been deopted before, skip...", reflected_method);
|
LOGD("method %p has been deopted before, skip...", reflected_method);
|
||||||
|
|
|
||||||
|
|
@ -31,10 +31,10 @@ namespace edxp {
|
||||||
LOGE("setNonCompilableNative: member is null");
|
LOGE("setNonCompilableNative: member is null");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
void *art_method = env->FromReflectedMethod(member);
|
void *art_method = getArtMethod(env, member);
|
||||||
|
|
||||||
if (!art_method || (long)art_method < 0x1000) {
|
if (!art_method) {
|
||||||
LOGE("setNonCompilableNative: art_method is null or invalid: %p", art_method);
|
LOGE("setNonCompilableNative: art_method is null");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setNonCompilable(art_method);
|
setNonCompilable(art_method);
|
||||||
|
|
@ -45,7 +45,7 @@ namespace edxp {
|
||||||
LOGE("setNativeFlagNative: member is null");
|
LOGE("setNativeFlagNative: member is null");
|
||||||
return JNI_FALSE;
|
return JNI_FALSE;
|
||||||
}
|
}
|
||||||
void *art_method = env->FromReflectedMethod(member);
|
void *art_method = getArtMethod(env, member);
|
||||||
if (!art_method) {
|
if (!art_method) {
|
||||||
LOGE("setNativeFlagNative: art_method is null");
|
LOGE("setNativeFlagNative: art_method is null");
|
||||||
return JNI_FALSE;
|
return JNI_FALSE;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue