Add an interface to deoptimize specified ArtMethod for Android Pie
This commit is contained in:
parent
c94f5543c0
commit
628d4e7ab0
|
|
@ -123,4 +123,6 @@ public class Main implements KeepAll {
|
||||||
public static native void closeFilesBeforeForkNative();
|
public static native void closeFilesBeforeForkNative();
|
||||||
|
|
||||||
public static native void reopenFilesAfterForkNative();
|
public static native void reopenFilesAfterForkNative();
|
||||||
|
|
||||||
|
public static native void deoptMethodNative(Object object);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -136,7 +136,7 @@ bool is_dynamic_modules_enabled() {
|
||||||
return dynamic_modules_enabled;
|
return dynamic_modules_enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
jstring get_installer_pkg_name(JNIEnv *env) {
|
jstring get_installer_pkg_name(JNIEnv *env, jclass clazz) {
|
||||||
init_once();
|
init_once();
|
||||||
return env->NewStringUTF(installer_package_name);
|
return env->NewStringUTF(installer_package_name);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,6 @@ bool is_black_white_list_enabled();
|
||||||
|
|
||||||
bool is_dynamic_modules_enabled();
|
bool is_dynamic_modules_enabled();
|
||||||
|
|
||||||
jstring get_installer_pkg_name(JNIEnv *env);
|
jstring get_installer_pkg_name(JNIEnv *env, jclass clazz);
|
||||||
|
|
||||||
#endif //EDXPOSED_CONFIG_MANAGER_H
|
#endif //EDXPOSED_CONFIG_MANAGER_H
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#include <inject/config_manager.h>
|
#include <inject/config_manager.h>
|
||||||
|
#include <native_hook/native_hook.h>
|
||||||
#include "java_hook/java_hook.h"
|
#include "java_hook/java_hook.h"
|
||||||
#include "include/logging.h"
|
#include "include/logging.h"
|
||||||
#include "include/fd_utils-inl.h"
|
#include "include/fd_utils-inl.h"
|
||||||
|
|
@ -64,6 +65,9 @@ static JNINativeMethod hookMethods[] = {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"reopenFilesAfterForkNative", "()V", (void *)reopenFilesAfterForkNative
|
"reopenFilesAfterForkNative", "()V", (void *)reopenFilesAfterForkNative
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"deoptMethodNative", "(Ljava/lang/Object;)V", (void *)deoptimize_method
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -102,7 +106,7 @@ void loadDexAndInit(JNIEnv *env, const char *dexPath) {
|
||||||
jclass entry_class = findClassFromLoader(env, myClassLoader, ENTRY_CLASS_NAME);
|
jclass entry_class = findClassFromLoader(env, myClassLoader, ENTRY_CLASS_NAME);
|
||||||
if (NULL != entry_class) {
|
if (NULL != entry_class) {
|
||||||
LOGD("HookEntry Class %p", entry_class);
|
LOGD("HookEntry Class %p", entry_class);
|
||||||
env->RegisterNatives(entry_class, hookMethods, 7);
|
env->RegisterNatives(entry_class, hookMethods, 8);
|
||||||
isInited = true;
|
isInited = true;
|
||||||
LOGD("RegisterNatives succeed for HookEntry.");
|
LOGD("RegisterNatives succeed for HookEntry.");
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -13,12 +13,20 @@ static const char *(*getDesc)(void *, std::string *);
|
||||||
|
|
||||||
static bool (*isInSamePackageBackup)(void *, void *) = nullptr;
|
static bool (*isInSamePackageBackup)(void *, void *) = nullptr;
|
||||||
|
|
||||||
|
// runtime
|
||||||
void *runtime_ = nullptr;
|
void *runtime_ = nullptr;
|
||||||
|
|
||||||
void (*deoptBootImage)(void *runtime) = nullptr;
|
void (*deoptBootImage)(void *runtime) = nullptr;
|
||||||
|
|
||||||
bool (*runtimeInitBackup)(void *runtime, void *mapAddr) = nullptr;
|
bool (*runtimeInitBackup)(void *runtime, void *mapAddr) = nullptr;
|
||||||
|
|
||||||
|
// instrumentation
|
||||||
|
void *instru_ = nullptr;
|
||||||
|
|
||||||
|
static void *(*instrCstBackup)(void *instru) = nullptr;
|
||||||
|
|
||||||
|
void (*deoptMethod)(void *, void *) = nullptr;
|
||||||
|
|
||||||
bool my_runtimeInit(void *runtime, void *mapAddr) {
|
bool my_runtimeInit(void *runtime, void *mapAddr) {
|
||||||
if (!runtimeInitBackup) {
|
if (!runtimeInitBackup) {
|
||||||
LOGE("runtimeInitBackup is null");
|
LOGE("runtimeInitBackup is null");
|
||||||
|
|
@ -45,7 +53,6 @@ static bool onIsInSamePackageCalled(void *thiz, void *that) {
|
||||||
|| strstr(thatDesc, "EdHooker") != nullptr
|
|| strstr(thatDesc, "EdHooker") != nullptr
|
||||||
|| strstr(thisDesc, "com/elderdrivers/riru/") != nullptr
|
|| strstr(thisDesc, "com/elderdrivers/riru/") != nullptr
|
||||||
|| strstr(thatDesc, "com/elderdrivers/riru/") != nullptr) {
|
|| strstr(thatDesc, "com/elderdrivers/riru/") != nullptr) {
|
||||||
// LOGE("onIsInSamePackageCalled, %s -> %s", thisDesc, thatDesc);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return (*isInSamePackageBackup)(thiz, that);
|
return (*isInSamePackageBackup)(thiz, that);
|
||||||
|
|
@ -61,7 +68,7 @@ static bool onInvokeHiddenAPI() {
|
||||||
* But we don't know the symbols until it's published.
|
* But we don't know the symbols until it's published.
|
||||||
* @author asLody
|
* @author asLody
|
||||||
*/
|
*/
|
||||||
static bool disable_HiddenAPIPolicyImpl(int api_level, void *artHandle,
|
static bool disableHiddenAPIPolicyImpl(int api_level, void *artHandle,
|
||||||
void (*hookFun)(void *, void *, void **)) {
|
void (*hookFun)(void *, void *, void **)) {
|
||||||
if (api_level < ANDROID_P) {
|
if (api_level < ANDROID_P) {
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -121,6 +128,59 @@ static void hookIsInSamePackage(int api_level, void *artHandle,
|
||||||
reinterpret_cast<void **>(&isInSamePackageBackup));
|
reinterpret_cast<void **>(&isInSamePackageBackup));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *my_instruCst(void *instru) {
|
||||||
|
if (!instrCstBackup) {
|
||||||
|
LOGE("instrCstBackup is null");
|
||||||
|
return instru;
|
||||||
|
}
|
||||||
|
LOGI("instrCst starts");
|
||||||
|
void *result = (*instrCstBackup)(instru);
|
||||||
|
LOGI("instrCst finishes");
|
||||||
|
if (instru_ != instru) {
|
||||||
|
LOGI("instru_ changed from %p to %p", instru_, instru);
|
||||||
|
instru_ = instru;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void hookInstrumentation(int api_level, void *artHandle, void (*hookFun)(void *, void *, void **)) {
|
||||||
|
if (api_level < ANDROID_P) {
|
||||||
|
// TODO support other api levels
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
void *instruCstSym = dlsym(artHandle,
|
||||||
|
"_ZN3art15instrumentation15InstrumentationC2Ev");
|
||||||
|
deoptMethod = reinterpret_cast<void (*)(void *, void *)>(
|
||||||
|
dlsym(artHandle,
|
||||||
|
"_ZN3art15instrumentation15Instrumentation40UpdateMethodsCodeToInterpreterEntryPointEPNS_9ArtMethodE"));
|
||||||
|
if (!instruCstSym) {
|
||||||
|
LOGE("can't get instruCstSym: %s", dlerror());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
(*hookFun)(instruCstSym, reinterpret_cast<void *>(my_instruCst),
|
||||||
|
reinterpret_cast<void **>(&instrCstBackup));
|
||||||
|
LOGI("instrCst hooked");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<void *> deoptedMethods;
|
||||||
|
|
||||||
|
void deoptimize_method(JNIEnv *env, jclass clazz, jobject method) {
|
||||||
|
if (!deoptMethod) {
|
||||||
|
LOGE("deoptMethodSym is null, skip deopt");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
void *reflected_method = env->FromReflectedMethod(method);
|
||||||
|
if (std::find(deoptedMethods.begin(), deoptedMethods.end(), reflected_method) !=
|
||||||
|
deoptedMethods.end()) {
|
||||||
|
LOGD("method %p has been deopted before, skip...", reflected_method);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LOGD("deoptimize method: %p", reflected_method);
|
||||||
|
(*deoptMethod)(instru_, reflected_method);
|
||||||
|
deoptedMethods.push_back(reflected_method);
|
||||||
|
LOGD("deoptimize method done: %p");
|
||||||
|
}
|
||||||
|
|
||||||
void hookRuntime(int api_level, void *artHandle, void (*hookFun)(void *, void *, void **)) {
|
void hookRuntime(int api_level, void *artHandle, void (*hookFun)(void *, void *, void **)) {
|
||||||
void *runtimeInitSym = nullptr;
|
void *runtimeInitSym = nullptr;
|
||||||
if (api_level >= ANDROID_O) {
|
if (api_level >= ANDROID_O) {
|
||||||
|
|
@ -177,12 +237,13 @@ void install_inline_hooks() {
|
||||||
LOGE("can't open libart: %s", dlerror());
|
LOGE("can't open libart: %s", dlerror());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
hookIsInSamePackage(api_level, artHandle, hookFun);
|
|
||||||
hookRuntime(api_level, artHandle, hookFun);
|
hookRuntime(api_level, artHandle, hookFun);
|
||||||
if (disable_HiddenAPIPolicyImpl(api_level, artHandle, hookFun)) {
|
hookInstrumentation(api_level, artHandle, hookFun);
|
||||||
LOGI("disable_HiddenAPIPolicyImpl done.");
|
hookIsInSamePackage(api_level, artHandle, hookFun);
|
||||||
|
if (disableHiddenAPIPolicyImpl(api_level, artHandle, hookFun)) {
|
||||||
|
LOGI("disableHiddenAPIPolicyImpl done.");
|
||||||
} else {
|
} else {
|
||||||
LOGE("disable_HiddenAPIPolicyImpl failed.");
|
LOGE("disableHiddenAPIPolicyImpl failed.");
|
||||||
}
|
}
|
||||||
dlclose(whaleHandle);
|
dlclose(whaleHandle);
|
||||||
dlclose(artHandle);
|
dlclose(artHandle);
|
||||||
|
|
|
||||||
|
|
@ -21,4 +21,6 @@ static constexpr const char *kLibWhalePath = "/system/lib/libwhale.so";
|
||||||
|
|
||||||
void install_inline_hooks();
|
void install_inline_hooks();
|
||||||
|
|
||||||
|
void deoptimize_method(JNIEnv *env, jclass clazz, jobject method);
|
||||||
|
|
||||||
#endif // HOOK_H
|
#endif // HOOK_H
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue