Fix exceptions when hooking pending methods

This commit is contained in:
solohsu 2019-06-16 00:53:21 +08:00
parent 12dcfed0f3
commit c5791951db
8 changed files with 52 additions and 28 deletions

View File

@ -36,4 +36,4 @@ only_commits:
- gradle.properties - gradle.properties
- appveyor.yml - appveyor.yml
version: '0.4.4.4_alpha (4441) {build}' version: '0.4.4.5_alpha (4450) {build}'

View File

@ -4,13 +4,13 @@ import com.elderdrivers.riru.common.KeepAll;
import java.lang.reflect.Member; import java.lang.reflect.Member;
import de.robv.android.xposed.XposedBridge; import de.robv.android.xposed.PendingHooks;
public class ClassLinker implements KeepAll { public class ClassLinker implements KeepAll {
public static native void setEntryPointsToInterpreter(Member method); public static native void setEntryPointsToInterpreter(Member method);
public static void onPostFixupStaticTrampolines(Class clazz) { public static void onPostFixupStaticTrampolines(Class clazz) {
XposedBridge.hookPendingMethod(clazz); PendingHooks.hookPendingMethod(clazz);
} }
} }

View File

@ -3,10 +3,10 @@ import org.gradle.internal.os.OperatingSystem
apply plugin: 'com.android.library' apply plugin: 'com.android.library'
version "v0.4.4.4_alpha" version "v0.4.4.5_alpha"
ext { ext {
versionCode = "4441" versionCode = "4450"
module_name = "EdXposed" module_name = "EdXposed"
jar_dest_dir = "${projectDir}/template_override/system/framework/" jar_dest_dir = "${projectDir}/template_override/system/framework/"
is_windows = OperatingSystem.current().isWindows() is_windows = OperatingSystem.current().isWindows()

View File

@ -16,7 +16,10 @@ namespace art {
CREATE_FUNC_SYMBOL_ENTRY(const char *, GetDescriptor, void *thiz, CREATE_FUNC_SYMBOL_ENTRY(const char *, GetDescriptor, void *thiz,
std::string *storage) { std::string *storage) {
return GetDescriptorSym(thiz, storage); if (GetDescriptorSym)
return GetDescriptorSym(thiz, storage);
else
return "";
} }
CREATE_HOOK_STUB_ENTRIES(bool, IsInSamePackage, void *thiz, void *that) { CREATE_HOOK_STUB_ENTRIES(bool, IsInSamePackage, void *thiz, void *that) {
@ -57,6 +60,13 @@ namespace art {
// HOOK_FUNC(ClassForName, // HOOK_FUNC(ClassForName,
// "_ZN3artL18Class_classForNameEP7_JNIEnvP7_jclassP8_jstringhP8_jobject"); // "_ZN3artL18Class_classForNameEP7_JNIEnvP7_jclassP8_jstringhP8_jobject");
} }
const char *GetDescriptor(std::string *storage) {
if (thiz_ && GetDescriptorSym) {
return GetDescriptor(thiz_, storage);
}
return "";
}
}; };
} // namespace mirror } // namespace mirror

View File

@ -11,6 +11,8 @@
#include <jni/edxp_resources_hook.h> #include <jni/edxp_resources_hook.h>
#include <dl_util.h> #include <dl_util.h>
#include <art/runtime/jni_env_ext.h> #include <art/runtime/jni_env_ext.h>
#include <art/runtime/mirror/class.h>
#include <android-base/strings.h>
#include "edxp_context.h" #include "edxp_context.h"
#include "config_manager.h" #include "config_manager.h"
@ -36,11 +38,16 @@ namespace edxp {
if (UNLIKELY(!post_fixup_static_mid_ || !class_linker_class_)) { if (UNLIKELY(!post_fixup_static_mid_ || !class_linker_class_)) {
return; return;
} }
if (!class_ptr) {
return;
}
JNIEnv *env; JNIEnv *env;
vm_->GetEnv((void **) (&env), JNI_VERSION_1_4); vm_->GetEnv((void **) (&env), JNI_VERSION_1_4);
art::JNIEnvExt env_ext(env); art::JNIEnvExt env_ext(env);
ScopedLocalRef clazz(env, env_ext.NewLocalRefer(class_ptr)); ScopedLocalRef clazz(env, env_ext.NewLocalRefer(class_ptr));
JNI_CallStaticVoidMethod(env, class_linker_class_, post_fixup_static_mid_, clazz.get()); if (clazz != nullptr) {
JNI_CallStaticVoidMethod(env, class_linker_class_, post_fixup_static_mid_, clazz.get());
}
} }
void Context::LoadDexAndInit(JNIEnv *env, const char *dex_path) { void Context::LoadDexAndInit(JNIEnv *env, const char *dex_path) {
@ -169,7 +176,7 @@ namespace edxp {
if (LIKELY(mid)) { if (LIKELY(mid)) {
va_list args; va_list args;
va_start(args, method_sig); va_start(args, method_sig);
env->functions->CallStaticVoidMethodV(env, entry_class_, mid, args); env->CallStaticVoidMethodV(entry_class_, mid, args);
va_end(args); va_end(args);
} else { } else {
LOGE("method %s id is null", method_name); LOGE("method %s id is null", method_name);

View File

@ -1,6 +1,6 @@
#!/system/bin/sh #!/system/bin/sh
EDXP_VERSION="0.4.4.4_alpha (4441)" EDXP_VERSION="0.4.4.5_alpha (4450)"
ANDROID_SDK=`getprop ro.build.version.sdk` ANDROID_SDK=`getprop ro.build.version.sdk`
BUILD_DESC=`getprop ro.build.description` BUILD_DESC=`getprop ro.build.description`
PRODUCT=`getprop ro.build.product` PRODUCT=`getprop ro.build.product`

View File

@ -0,0 +1,24 @@
package de.robv.android.xposed;
import java.lang.reflect.Member;
import java.util.concurrent.ConcurrentHashMap;
import static de.robv.android.xposed.XposedBridge.hookMethodNative;
public final class PendingHooks {
private static final ConcurrentHashMap<Member, XposedBridge.AdditionalHookInfo>
sPendingHookMethods = new ConcurrentHashMap<>();
public synchronized static void hookPendingMethod(Class clazz) {
for (Member member : sPendingHookMethods.keySet()) {
if (member.getDeclaringClass().equals(clazz)) {
hookMethodNative(member, clazz, 0, sPendingHookMethods.get(member));
}
}
}
public synchronized static void recordPendingMethod(Member hookMethod, XposedBridge.AdditionalHookInfo additionalInfo) {
sPendingHookMethods.put(hookMethod, additionalInfo);
}
}

View File

@ -18,7 +18,6 @@ import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import dalvik.system.InMemoryDexClassLoader; import dalvik.system.InMemoryDexClassLoader;
import de.robv.android.xposed.XC_MethodHook.MethodHookParam; import de.robv.android.xposed.XC_MethodHook.MethodHookParam;
@ -235,29 +234,13 @@ public final class XposedBridge {
if (reflectMethod != null) { if (reflectMethod != null) {
hookMethodNative(reflectMethod, declaringClass, slot, additionalInfo); hookMethodNative(reflectMethod, declaringClass, slot, additionalInfo);
} else { } else {
synchronized (pendingLock) { PendingHooks.recordPendingMethod(hookMethod, additionalInfo);
sPendingHookMethods.put(hookMethod, additionalInfo);
}
} }
} }
return callback.new Unhook(hookMethod); return callback.new Unhook(hookMethod);
} }
private static final ConcurrentHashMap<Member, XposedBridge.AdditionalHookInfo>
sPendingHookMethods = new ConcurrentHashMap<>();
private static final Object pendingLock = new Object();
public static void hookPendingMethod(Class clazz) {
synchronized (pendingLock) {
for (Member member : sPendingHookMethods.keySet()) {
if (member.getDeclaringClass().equals(clazz)) {
hookMethodNative(member, clazz, 0, sPendingHookMethods.get(member));
}
}
}
}
/** /**
* Removes the callback for a hooked method/constructor. * Removes the callback for a hooked method/constructor.
* *
@ -448,7 +431,7 @@ public final class XposedBridge {
* Intercept every call to the specified method and call a handler function instead. * Intercept every call to the specified method and call a handler function instead.
* @param method The method to intercept * @param method The method to intercept
*/ */
private synchronized static void hookMethodNative(final Member method, Class<?> declaringClass, /*package*/ synchronized static void hookMethodNative(final Member method, Class<?> declaringClass,
int slot, final Object additionalInfoObj) { int slot, final Object additionalInfoObj) {
EdXpConfigGlobal.getHookProvider().hookMethod(method, (AdditionalHookInfo) additionalInfoObj); EdXpConfigGlobal.getHookProvider().hookMethod(method, (AdditionalHookInfo) additionalInfoObj);
} }