Move inline hooks to post fork
This commit is contained in:
parent
51dfa6b19f
commit
d6c7570588
|
|
@ -41,67 +41,67 @@ ALWAYS_INLINE static int ClearException(JNIEnv *env) {
|
||||||
|
|
||||||
#define JNI_FindClass(env, name) \
|
#define JNI_FindClass(env, name) \
|
||||||
env->FindClass(name); \
|
env->FindClass(name); \
|
||||||
if (ClearException(env)) LOGE("FindClass " #name);
|
if (ClearException(env)) LOGE("FindClass " #name)
|
||||||
|
|
||||||
#define JNI_GetObjectClass(env, obj) \
|
#define JNI_GetObjectClass(env, obj) \
|
||||||
env->GetObjectClass(obj); \
|
env->GetObjectClass(obj); \
|
||||||
if (ClearException(env)) LOGE("GetObjectClass " #obj);
|
if (ClearException(env)) LOGE("GetObjectClass " #obj)
|
||||||
|
|
||||||
#define JNI_GetFieldID(env, class, name, sig) \
|
#define JNI_GetFieldID(env, class, name, sig) \
|
||||||
env->GetFieldID(class, name, sig); \
|
env->GetFieldID(class, name, sig); \
|
||||||
if (ClearException(env)) LOGE("GetFieldID " #name);
|
if (ClearException(env)) LOGE("GetFieldID " #name)
|
||||||
|
|
||||||
#define JNI_GetObjectField(env, class, fieldId) \
|
#define JNI_GetObjectField(env, class, fieldId) \
|
||||||
env->GetObjectField(class, fieldId); \
|
env->GetObjectField(class, fieldId); \
|
||||||
if (ClearException(env)) LOGE("GetObjectField " #fieldId);
|
if (ClearException(env)) LOGE("GetObjectField " #fieldId)
|
||||||
|
|
||||||
#define JNI_GetMethodID(env, class, name, sig) \
|
#define JNI_GetMethodID(env, class, name, sig) \
|
||||||
env->GetMethodID(class, name, sig); \
|
env->GetMethodID(class, name, sig); \
|
||||||
if (ClearException(env)) LOGE("GetMethodID " #name);
|
if (ClearException(env)) LOGE("GetMethodID " #name)
|
||||||
|
|
||||||
#define JNI_CallObjectMethod(env, obj, ...) \
|
#define JNI_CallObjectMethod(env, obj, ...) \
|
||||||
env->CallObjectMethod(obj, __VA_ARGS__); \
|
env->CallObjectMethod(obj, __VA_ARGS__); \
|
||||||
if (ClearException(env)) LOGE("CallObjectMethod " #obj " " #__VA_ARGS__);
|
if (ClearException(env)) LOGE("CallObjectMethod " #obj " " #__VA_ARGS__)
|
||||||
|
|
||||||
#define JNI_CallVoidMethod(env, obj, ...) \
|
#define JNI_CallVoidMethod(env, obj, ...) \
|
||||||
env->CallVoidMethod(obj, __VA_ARGS__); \
|
env->CallVoidMethod(obj, __VA_ARGS__); \
|
||||||
if (ClearException(env)) LOGE("CallVoidMethod " #obj " " #__VA_ARGS__);
|
if (ClearException(env)) LOGE("CallVoidMethod " #obj " " #__VA_ARGS__)
|
||||||
|
|
||||||
#define JNI_GetStaticFieldID(env, class, name, sig) \
|
#define JNI_GetStaticFieldID(env, class, name, sig) \
|
||||||
env->GetStaticFieldID(class, name, sig); \
|
env->GetStaticFieldID(class, name, sig); \
|
||||||
if (ClearException(env)) LOGE("GetStaticFieldID " #name " " #sig);
|
if (ClearException(env)) LOGE("GetStaticFieldID " #name " " #sig)
|
||||||
|
|
||||||
#define JNI_GetStaticObjectField(env, class, fieldId) \
|
#define JNI_GetStaticObjectField(env, class, fieldId) \
|
||||||
env->GetStaticObjectField(class, fieldId); \
|
env->GetStaticObjectField(class, fieldId); \
|
||||||
if (ClearException(env)) LOGE("GetStaticObjectField " #fieldId);
|
if (ClearException(env)) LOGE("GetStaticObjectField " #fieldId)
|
||||||
|
|
||||||
#define JNI_GetStaticMethodID(env, class, name, sig) \
|
#define JNI_GetStaticMethodID(env, class, name, sig) \
|
||||||
env->GetStaticMethodID(class, name, sig); \
|
env->GetStaticMethodID(class, name, sig); \
|
||||||
if (ClearException(env)) LOGE("GetStaticMethodID " #name);
|
if (ClearException(env)) LOGE("GetStaticMethodID " #name)
|
||||||
|
|
||||||
#define JNI_CallStaticVoidMethod(env, obj, ...) \
|
#define JNI_CallStaticVoidMethod(env, obj, ...) \
|
||||||
env->CallStaticVoidMethod(obj, __VA_ARGS__); \
|
env->CallStaticVoidMethod(obj, __VA_ARGS__); \
|
||||||
if (ClearException(env)) LOGE("CallStaticVoidMethod " #obj " " #__VA_ARGS__);
|
if (ClearException(env)) LOGE("CallStaticVoidMethod " #obj " " #__VA_ARGS__)
|
||||||
|
|
||||||
#define JNI_CallStaticObjectMethod(env, obj, ...) \
|
#define JNI_CallStaticObjectMethod(env, obj, ...) \
|
||||||
env->CallStaticObjectMethod(obj, __VA_ARGS__); \
|
env->CallStaticObjectMethod(obj, __VA_ARGS__); \
|
||||||
if (ClearException(env)) LOGE("CallStaticObjectMethod " #obj " " #__VA_ARGS__);
|
if (ClearException(env)) LOGE("CallStaticObjectMethod " #obj " " #__VA_ARGS__)
|
||||||
|
|
||||||
#define JNI_CallStaticIntMethod(env, obj, ...) \
|
#define JNI_CallStaticIntMethod(env, obj, ...) \
|
||||||
env->CallStaticIntMethod(obj, __VA_ARGS__); \
|
env->CallStaticIntMethod(obj, __VA_ARGS__); \
|
||||||
if (ClearException(env)) LOGE("CallStaticIntMethod " #obj " " #__VA_ARGS__);
|
if (ClearException(env)) LOGE("CallStaticIntMethod " #obj " " #__VA_ARGS__)
|
||||||
|
|
||||||
#define JNI_GetArrayLength(env, array) \
|
#define JNI_GetArrayLength(env, array) \
|
||||||
env->GetArrayLength(array); \
|
env->GetArrayLength(array); \
|
||||||
if (ClearException(env)) LOGE("GetArrayLength " #array);
|
if (ClearException(env)) LOGE("GetArrayLength " #array)
|
||||||
|
|
||||||
#define JNI_NewObject(env, class, ...) \
|
#define JNI_NewObject(env, class, ...) \
|
||||||
env->NewObject(class, __VA_ARGS__); \
|
env->NewObject(class, __VA_ARGS__); \
|
||||||
if (ClearException(env)) LOGE("NewObject " #class " " #__VA_ARGS__);
|
if (ClearException(env)) LOGE("NewObject " #class " " #__VA_ARGS__)
|
||||||
|
|
||||||
#define JNI_RegisterNatives(env, class, methods, size) \
|
#define JNI_RegisterNatives(env, class, methods, size) \
|
||||||
env->RegisterNatives(class, methods, size); \
|
env->RegisterNatives(class, methods, size); \
|
||||||
if (ClearException(env)) LOGE("RegisterNatives " #class);
|
if (ClearException(env)) LOGE("RegisterNatives " #class)
|
||||||
|
|
||||||
class JUTFString {
|
class JUTFString {
|
||||||
public:
|
public:
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,8 @@ namespace art {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CREATE_HOOK_STUB_ENTRIES(bool, ShouldUseInterpreterEntrypoint, void *art_method, const void* quick_code) {
|
CREATE_HOOK_STUB_ENTRIES(bool, ShouldUseInterpreterEntrypoint, void *art_method,
|
||||||
|
const void *quick_code) {
|
||||||
// TODO check hooked
|
// TODO check hooked
|
||||||
bool hooked = false;
|
bool hooked = false;
|
||||||
if (hooked && quick_code != nullptr) {
|
if (hooked && quick_code != nullptr) {
|
||||||
|
|
@ -68,46 +69,47 @@ namespace art {
|
||||||
// TODO: Maybe not compatible with Android 10-
|
// TODO: Maybe not compatible with Android 10-
|
||||||
int api_level = edxp::GetAndroidApiLevel();
|
int api_level = edxp::GetAndroidApiLevel();
|
||||||
size_t OFFSET_classlinker; // Get offset from art::Runtime::RunRootClinits() call in IDA
|
size_t OFFSET_classlinker; // Get offset from art::Runtime::RunRootClinits() call in IDA
|
||||||
switch(api_level) {
|
switch (api_level) {
|
||||||
case __ANDROID_API_O__:
|
case __ANDROID_API_O__:
|
||||||
|
[[fallthrough]];
|
||||||
case __ANDROID_API_O_MR1__:
|
case __ANDROID_API_O_MR1__:
|
||||||
#ifdef __LP64__
|
if constexpr(edxp::is64) {
|
||||||
OFFSET_classlinker = 464 / 8;
|
OFFSET_classlinker = 464;
|
||||||
#else
|
} else {
|
||||||
OFFSET_classlinker = 284 / 4;
|
OFFSET_classlinker = 284;
|
||||||
#endif
|
}
|
||||||
break;
|
break;
|
||||||
case __ANDROID_API_P__:
|
case __ANDROID_API_P__:
|
||||||
#ifdef __LP64__
|
if constexpr(edxp::is64) {
|
||||||
OFFSET_classlinker = 528 / 8;
|
OFFSET_classlinker = 528;
|
||||||
#else
|
} else {
|
||||||
OFFSET_classlinker = 336 / 4;
|
OFFSET_classlinker = 336;
|
||||||
#endif
|
}
|
||||||
break;
|
break;
|
||||||
case __ANDROID_API_Q__:
|
case __ANDROID_API_Q__:
|
||||||
#ifdef __LP64__
|
if constexpr(edxp::is64) {
|
||||||
OFFSET_classlinker = 480 / 8;
|
OFFSET_classlinker = 480;
|
||||||
#else
|
} else {
|
||||||
OFFSET_classlinker = 280 / 4;
|
OFFSET_classlinker = 280;
|
||||||
#endif
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LOGE("No valid offset for art::Runtime::class_linker_ found. Using Android R.");
|
LOGE("No valid offset for art::Runtime::class_linker_ found. Using Android R.");
|
||||||
|
[[fallthrough]];
|
||||||
case __ANDROID_API_R__:
|
case __ANDROID_API_R__:
|
||||||
#ifdef __LP64__
|
if constexpr(edxp::is64) {
|
||||||
OFFSET_classlinker = 472 / 8;
|
OFFSET_classlinker = 472;
|
||||||
#else
|
} else {
|
||||||
OFFSET_classlinker = 276 / 4;
|
OFFSET_classlinker = 276;
|
||||||
#endif
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *thiz = *reinterpret_cast<void **>(
|
||||||
|
reinterpret_cast<size_t>(Runtime::Current()->Get()) + OFFSET_classlinker);
|
||||||
// ClassLinker* GetClassLinker() but inlined
|
// ClassLinker* GetClassLinker() but inlined
|
||||||
void* cl = reinterpret_cast<void*>(
|
LOGD("Classlinker object: %p", thiz);
|
||||||
reinterpret_cast<size_t*>(Runtime::Current()->Get()) + OFFSET_classlinker
|
instance_ = new ClassLinker(thiz);
|
||||||
);
|
|
||||||
LOGD("Classlinker object: %p", cl);
|
|
||||||
instance_ = new ClassLinker(cl);
|
|
||||||
|
|
||||||
HOOK_FUNC(Constructor, "_ZN3art11ClassLinkerC2EPNS_11InternTableE",
|
HOOK_FUNC(Constructor, "_ZN3art11ClassLinkerC2EPNS_11InternTableE",
|
||||||
"_ZN3art11ClassLinkerC2EPNS_11InternTableEb"); // 10.0
|
"_ZN3art11ClassLinkerC2EPNS_11InternTableEb"); // 10.0
|
||||||
|
|
@ -119,7 +121,8 @@ namespace art {
|
||||||
|
|
||||||
// Sandhook will hook ShouldUseInterpreterEntrypoint, so we just skip
|
// Sandhook will hook ShouldUseInterpreterEntrypoint, so we just skip
|
||||||
// edxp::Context::GetInstance()->GetVariant() will not work here, so we use smh dirty hack
|
// edxp::Context::GetInstance()->GetVariant() will not work here, so we use smh dirty hack
|
||||||
if (api_level >= __ANDROID_API_R__ && access(edxp::kLibSandHookNativePath.c_str(), F_OK) == -1) {
|
if (api_level >= __ANDROID_API_R__ &&
|
||||||
|
access(edxp::kLibSandHookNativePath.c_str(), F_OK) == -1) {
|
||||||
LOGD("Not sandhook, installing _ZN3art11ClassLinker30ShouldUseInterpreterEntrypointEPNS_9ArtMethodEPKv");
|
LOGD("Not sandhook, installing _ZN3art11ClassLinker30ShouldUseInterpreterEntrypointEPNS_9ArtMethodEPKv");
|
||||||
HOOK_FUNC(ShouldUseInterpreterEntrypoint,
|
HOOK_FUNC(ShouldUseInterpreterEntrypoint,
|
||||||
"_ZN3art11ClassLinker30ShouldUseInterpreterEntrypointEPNS_9ArtMethodEPKv");
|
"_ZN3art11ClassLinker30ShouldUseInterpreterEntrypointEPNS_9ArtMethodEPKv");
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
#include "collector/gc_type.h"
|
#include "collector/gc_type.h"
|
||||||
#include "gc_cause.h"
|
#include "gc_cause.h"
|
||||||
#include "../thread.h"
|
#include "../thread.h"
|
||||||
|
#include "../runtime.h"
|
||||||
|
|
||||||
namespace art {
|
namespace art {
|
||||||
|
|
||||||
|
|
@ -22,14 +23,6 @@ namespace art {
|
||||||
return art::gc::collector::GcType::kGcTypeNone;
|
return art::gc::collector::GcType::kGcTypeNone;
|
||||||
}
|
}
|
||||||
|
|
||||||
CREATE_HOOK_STUB_ENTRIES(void, PreZygoteFork, void *thiz) {
|
|
||||||
if (instance_)
|
|
||||||
instance_->Reset(thiz);
|
|
||||||
else
|
|
||||||
instance_ = new Heap(thiz);
|
|
||||||
PreZygoteForkBackup(thiz);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Heap(void *thiz) : HookedObject(thiz) {}
|
Heap(void *thiz) : HookedObject(thiz) {}
|
||||||
|
|
||||||
|
|
@ -39,7 +32,47 @@ namespace art {
|
||||||
|
|
||||||
// @ApiSensitive(Level.MIDDLE)
|
// @ApiSensitive(Level.MIDDLE)
|
||||||
static void Setup(void *handle, HookFunType hook_func) {
|
static void Setup(void *handle, HookFunType hook_func) {
|
||||||
HOOK_FUNC(PreZygoteFork, "_ZN3art2gc4Heap13PreZygoteForkEv");
|
int api_level = edxp::GetAndroidApiLevel();
|
||||||
|
size_t OFFSET_classlinker; // Get offset from art::Runtime::RunRootClinits() call in IDA
|
||||||
|
switch (api_level) {
|
||||||
|
case __ANDROID_API_O__:
|
||||||
|
[[fallthrough]];
|
||||||
|
case __ANDROID_API_O_MR1__:
|
||||||
|
if constexpr(edxp::is64) {
|
||||||
|
OFFSET_classlinker = 464;
|
||||||
|
} else {
|
||||||
|
OFFSET_classlinker = 284;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case __ANDROID_API_P__:
|
||||||
|
if constexpr(edxp::is64) {
|
||||||
|
OFFSET_classlinker = 528;
|
||||||
|
} else {
|
||||||
|
OFFSET_classlinker = 336;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case __ANDROID_API_Q__:
|
||||||
|
if constexpr(edxp::is64) {
|
||||||
|
OFFSET_classlinker = 480;
|
||||||
|
} else {
|
||||||
|
OFFSET_classlinker = 280;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOGE("No valid offset for art::Runtime::class_linker_ found. Using Android R.");
|
||||||
|
[[fallthrough]];
|
||||||
|
case __ANDROID_API_R__:
|
||||||
|
if constexpr(edxp::is64) {
|
||||||
|
OFFSET_classlinker = 392;
|
||||||
|
} else {
|
||||||
|
OFFSET_classlinker = 236;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
void *thiz = *reinterpret_cast<void **>(
|
||||||
|
reinterpret_cast<size_t>(Runtime::Current()->Get()) + OFFSET_classlinker);
|
||||||
|
LOGD("HEAP object: %p", thiz);
|
||||||
|
instance_ = new Heap(thiz);
|
||||||
RETRIEVE_FUNC_SYMBOL(WaitForGcToComplete,
|
RETRIEVE_FUNC_SYMBOL(WaitForGcToComplete,
|
||||||
"_ZN3art2gc4Heap19WaitForGcToCompleteENS0_7GcCauseEPNS_6ThreadE");
|
"_ZN3art2gc4Heap19WaitForGcToCompleteENS0_7GcCauseEPNS_6ThreadE");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,19 +16,6 @@ namespace art {
|
||||||
DeoptimizeBootImageSym(thiz);
|
DeoptimizeBootImageSym(thiz);
|
||||||
}
|
}
|
||||||
|
|
||||||
CREATE_HOOK_STUB_ENTRIES(bool, Init, void *thiz, void *runtime_options) {
|
|
||||||
if (LIKELY(instance_))
|
|
||||||
instance_->Reset(thiz);
|
|
||||||
else
|
|
||||||
instance_ = new Runtime(thiz);
|
|
||||||
bool success = InitBackup(thiz, runtime_options);
|
|
||||||
if (edxp::ConfigManager::GetInstance()->IsDeoptBootImageEnabled()) {
|
|
||||||
DeoptimizeBootImage(thiz);
|
|
||||||
LOGI("DeoptimizeBootImage done");
|
|
||||||
}
|
|
||||||
return success;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Runtime(void *thiz) : HookedObject(thiz) {}
|
Runtime(void *thiz) : HookedObject(thiz) {}
|
||||||
|
|
||||||
|
|
@ -38,19 +25,13 @@ namespace art {
|
||||||
|
|
||||||
// @ApiSensitive(Level.LOW)
|
// @ApiSensitive(Level.LOW)
|
||||||
static void Setup(void *handle, HookFunType hook_func) {
|
static void Setup(void *handle, HookFunType hook_func) {
|
||||||
HOOK_FUNC(Init, "_ZN3art7Runtime4InitEONS_18RuntimeArgumentMapE");
|
|
||||||
RETRIEVE_FUNC_SYMBOL(DeoptimizeBootImage,
|
RETRIEVE_FUNC_SYMBOL(DeoptimizeBootImage,
|
||||||
"_ZN3art7Runtime19DeoptimizeBootImageEv");
|
"_ZN3art7Runtime19DeoptimizeBootImageEv");
|
||||||
RETRIEVE_FIELD_SYMBOL(thiz, "_ZN3art7Runtime9instance_E");
|
RETRIEVE_FIELD_SYMBOL(instance, "_ZN3art7Runtime9instance_E");
|
||||||
|
void * thiz = *reinterpret_cast<void**>(instance);
|
||||||
LOGD("_ZN3art7Runtime9instance_E = %p", thiz);
|
LOGD("_ZN3art7Runtime9instance_E = %p", thiz);
|
||||||
instance_ = new Runtime(thiz);
|
instance_ = new Runtime(thiz);
|
||||||
}
|
}
|
||||||
|
|
||||||
ALWAYS_INLINE void DeoptimizeBootImage() const {
|
|
||||||
if (LIKELY(thiz_))
|
|
||||||
DeoptimizeBootImage(thiz_);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,17 @@ namespace edxp {
|
||||||
//#define LOG_DISABLED
|
//#define LOG_DISABLED
|
||||||
//#define DEBUG
|
//#define DEBUG
|
||||||
|
|
||||||
|
|
||||||
|
inline bool constexpr Is64() {
|
||||||
|
#if defined(__LP64__)
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
inline constexpr bool is64 = Is64();
|
||||||
|
|
||||||
#if defined(__LP64__)
|
#if defined(__LP64__)
|
||||||
# define LP_SELECT(lp32, lp64) (lp64)
|
# define LP_SELECT(lp32, lp64) (lp64)
|
||||||
#else
|
#else
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,9 @@
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include "edxp_context.h"
|
#include "edxp_context.h"
|
||||||
#include "config_manager.h"
|
#include "config_manager.h"
|
||||||
|
#include "art/runtime/runtime.h"
|
||||||
|
#include "art/runtime/gc/heap.h"
|
||||||
|
#include "native_hook.h"
|
||||||
|
|
||||||
#pragma clang diagnostic push
|
#pragma clang diagnostic push
|
||||||
#pragma clang diagnostic ignored "-Wunused-value"
|
#pragma clang diagnostic ignored "-Wunused-value"
|
||||||
|
|
@ -242,9 +245,22 @@ namespace edxp {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int Context::OnNativeForkSystemServerPost(JNIEnv *env, jclass clazz, jint res) {
|
int
|
||||||
|
Context::OnNativeForkSystemServerPost(JNIEnv *env, [[maybe_unused]] jclass clazz, jint res) {
|
||||||
if (res == 0) {
|
if (res == 0) {
|
||||||
if (!skip_) {
|
if (!skip_) {
|
||||||
|
if (void *buf = mmap(nullptr, 1, PROT_READ | PROT_WRITE | PROT_EXEC,
|
||||||
|
MAP_ANONYMOUS | MAP_PRIVATE, -1,
|
||||||
|
0);
|
||||||
|
buf == MAP_FAILED) {
|
||||||
|
skip_ = true;
|
||||||
|
LOGE("skip injecting into android because sepolicy was not loaded properly");
|
||||||
|
} else {
|
||||||
|
munmap(buf, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!skip_) {
|
||||||
|
InstallInlineHooks();
|
||||||
PrepareJavaEnv(env);
|
PrepareJavaEnv(env);
|
||||||
// only do work in child since FindAndCall would print log
|
// only do work in child since FindAndCall would print log
|
||||||
FindAndCall(env, "forkSystemServerPost", "(I)V", res);
|
FindAndCall(env, "forkSystemServerPost", "(I)V", res);
|
||||||
|
|
@ -345,6 +361,7 @@ namespace edxp {
|
||||||
if (res == 0) {
|
if (res == 0) {
|
||||||
const JUTFString process_name(env, nice_name_);
|
const JUTFString process_name(env, nice_name_);
|
||||||
if (!skip_) {
|
if (!skip_) {
|
||||||
|
InstallInlineHooks();
|
||||||
PrepareJavaEnv(env);
|
PrepareJavaEnv(env);
|
||||||
LOGD("Done prepare");
|
LOGD("Done prepare");
|
||||||
FindAndCall(env, "forkAndSpecializePost",
|
FindAndCall(env, "forkAndSpecializePost",
|
||||||
|
|
|
||||||
|
|
@ -9,18 +9,17 @@
|
||||||
|
|
||||||
namespace edxp {
|
namespace edxp {
|
||||||
|
|
||||||
static std::vector<void *> deopted_methods;
|
static std::unordered_set<void *> deopted_methods;
|
||||||
|
|
||||||
static void ClassLinker_setEntryPointsToInterpreter(JNI_START, jobject method) {
|
static void ClassLinker_setEntryPointsToInterpreter(JNI_START, jobject method) {
|
||||||
void *reflected_method = getArtMethod(env, method);
|
void *reflected_method = getArtMethod(env, method);
|
||||||
if (std::find(deopted_methods.begin(), deopted_methods.end(), reflected_method) !=
|
if (deopted_methods.count(reflected_method)) {
|
||||||
deopted_methods.end()) {
|
|
||||||
LOGD("method %p has been deopted before, skip...", reflected_method);
|
LOGD("method %p has been deopted before, skip...", reflected_method);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
LOGD("deoptimizing method: %p", reflected_method);
|
LOGD("deoptimizing method: %p", reflected_method);
|
||||||
art::ClassLinker::Current()->SetEntryPointsToInterpreter(reflected_method);
|
art::ClassLinker::Current()->SetEntryPointsToInterpreter(reflected_method);
|
||||||
deopted_methods.push_back(reflected_method);
|
deopted_methods.insert(reflected_method);
|
||||||
LOGD("method deoptimized: %p", reflected_method);
|
LOGD("method deoptimized: %p", reflected_method);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,6 @@ namespace edxp {
|
||||||
// TODO exclude unrelated processes
|
// TODO exclude unrelated processes
|
||||||
static void onModuleLoaded() {
|
static void onModuleLoaded() {
|
||||||
LOG(INFO) << "onModuleLoaded: welcome to EdXposed!";
|
LOG(INFO) << "onModuleLoaded: welcome to EdXposed!";
|
||||||
InstallInlineHooks();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int shouldSkipUid(int uid) {
|
static int shouldSkipUid(int uid) {
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ namespace edxp {
|
||||||
|
|
||||||
static volatile bool installed = false;
|
static volatile bool installed = false;
|
||||||
static volatile bool art_hooks_installed = false;
|
static volatile bool art_hooks_installed = false;
|
||||||
static HookFunType hook_func = nullptr;
|
static HookFunType hook_func = reinterpret_cast<HookFunType>(DobbyHook);
|
||||||
|
|
||||||
void InstallArtHooks(void *art_handle);
|
void InstallArtHooks(void *art_handle);
|
||||||
|
|
||||||
|
|
@ -42,8 +42,6 @@ namespace edxp {
|
||||||
}
|
}
|
||||||
LOGI("Using api level %d", api_level);
|
LOGI("Using api level %d", api_level);
|
||||||
InstallRiruHooks();
|
InstallRiruHooks();
|
||||||
hook_func = reinterpret_cast<HookFunType>(DobbyHook);
|
|
||||||
|
|
||||||
// install ART hooks
|
// install ART hooks
|
||||||
if (api_level >= __ANDROID_API_Q__) {
|
if (api_level >= __ANDROID_API_Q__) {
|
||||||
// From Riru v22 we can't get ART handle by hooking dlopen, so we get libart.so from soinfo.
|
// From Riru v22 we can't get ART handle by hooking dlopen, so we get libart.so from soinfo.
|
||||||
|
|
@ -73,9 +71,7 @@ namespace edxp {
|
||||||
if (art_hooks_installed) {
|
if (art_hooks_installed) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (ConfigManager::GetInstance()->IsHiddenAPIBypassEnabled()) {
|
art::hidden_api::DisableHiddenApi(art_handle, hook_func);
|
||||||
art::hidden_api::DisableHiddenApi(art_handle, hook_func);
|
|
||||||
}
|
|
||||||
art::Runtime::Setup(art_handle, hook_func);
|
art::Runtime::Setup(art_handle, hook_func);
|
||||||
art::gc::Heap::Setup(art_handle, hook_func);
|
art::gc::Heap::Setup(art_handle, hook_func);
|
||||||
art::ClassLinker::Setup(art_handle, hook_func);
|
art::ClassLinker::Setup(art_handle, hook_func);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue