Uniform the use of new ArtMethod resolution strategy

This commit is contained in:
solohsu 2020-08-02 01:00:42 +08:00
parent 6b7c8e4942
commit 0336a2aa29
6 changed files with 29 additions and 23 deletions

View File

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

View File

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

View File

@ -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

View File

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

View File

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

View File

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