Use a more stable symbol to deoptimize method

Now deoptMethod API supports all Android versions >= 6.0
This commit is contained in:
solohsu 2019-03-10 08:28:41 +08:00
parent 88e0d33c2a
commit b5b3280c9f
2 changed files with 31 additions and 28 deletions

View File

@ -92,6 +92,7 @@ public final class XposedInit {
&& !ConfigManager.isDynamicModulesMode()) { && !ConfigManager.isDynamicModulesMode()) {
return; return;
} }
// FIXME module list is cleared but never could be reload again when using dynamic-module-list under multi-user environment
XposedBridge.clearLoadedPackages(); XposedBridge.clearLoadedPackages();
final String filename = INSTALLER_DATA_BASE_DIR + "conf/modules.list"; final String filename = INSTALLER_DATA_BASE_DIR + "conf/modules.list";
BaseService service = SELinuxHelper.getAppDataFileService(); BaseService service = SELinuxHelper.getAppDataFileService();

View File

@ -21,10 +21,9 @@ void (*deoptBootImage)(void *runtime) = nullptr;
bool (*runtimeInitBackup)(void *runtime, void *mapAddr) = nullptr; bool (*runtimeInitBackup)(void *runtime, void *mapAddr) = nullptr;
// instrumentation void *class_linker_ = nullptr;
void *instru_ = nullptr;
static void *(*instrCstBackup)(void *instru) = nullptr; static void *(*classLinkerCstBackup)(void *, void *) = nullptr;
void (*deoptMethod)(void *, void *) = nullptr; void (*deoptMethod)(void *, void *) = nullptr;
@ -131,38 +130,38 @@ static void hookIsInSamePackage(int api_level, void *artHandle,
reinterpret_cast<void **>(&isInSamePackageBackup)); reinterpret_cast<void **>(&isInSamePackageBackup));
} }
void *my_instruCst(void *instru) { void *my_classLinkerCst(void *classLinker, void *internTable) {
if (!instrCstBackup) { LOGI("classLinkerCst starts");
LOGE("instrCstBackup is null"); void *result = (*classLinkerCstBackup)(classLinker, internTable);
return instru; if (class_linker_ != classLinker) {
} LOGI("class_linker_ changed from %p to %p", class_linker_, classLinker);
LOGI("instrCst starts"); class_linker_ = classLinker;
void *result = (*instrCstBackup)(instru);
LOGI("instrCst finishes");
if (instru_ != instru) {
LOGI("instru_ changed from %p to %p", instru_, instru);
instru_ = instru;
} }
LOGI("classLinkerCst finishes");
return result; return result;
} }
void hookInstrumentation(int api_level, void *artHandle, void (*hookFun)(void *, void *, void **)) { void hookInstrumentation(int api_level, void *artHandle, void (*hookFun)(void *, void *, void **)) {
if (api_level < ANDROID_P) { if (api_level < ANDROID_M) {
// TODO support other api levels // 5.x not supported
return;
}
void *classLinkerCstSym = dlsym(artHandle,
"_ZN3art11ClassLinkerC2EPNS_11InternTableE");
if (!classLinkerCstSym) {
LOGE("can't get classLinkerCstSym: %s", dlerror());
return; return;
} }
void *instruCstSym = dlsym(artHandle,
"_ZN3art15instrumentation15InstrumentationC2Ev");
deoptMethod = reinterpret_cast<void (*)(void *, void *)>( deoptMethod = reinterpret_cast<void (*)(void *, void *)>(
dlsym(artHandle, dlsym(artHandle,
"_ZN3art15instrumentation15Instrumentation40UpdateMethodsCodeToInterpreterEntryPointEPNS_9ArtMethodE")); "_ZNK3art11ClassLinker27SetEntryPointsToInterpreterEPNS_9ArtMethodE"));
if (!instruCstSym) { if (!deoptMethod) {
LOGE("can't get instruCstSym: %s", dlerror()); LOGE("can't get deoptMethodSym: %s", dlerror());
return; return;
} }
(*hookFun)(instruCstSym, reinterpret_cast<void *>(my_instruCst), (*hookFun)(classLinkerCstSym, reinterpret_cast<void *>(my_classLinkerCst),
reinterpret_cast<void **>(&instrCstBackup)); reinterpret_cast<void **>(&classLinkerCstBackup));
LOGI("instrCst hooked"); LOGI("classLinkerCst hooked");
} }
std::vector<void *> deoptedMethods; std::vector<void *> deoptedMethods;
@ -172,16 +171,20 @@ void deoptimize_method(JNIEnv *env, jclass clazz, jobject method) {
LOGE("deoptMethodSym is null, skip deopt"); LOGE("deoptMethodSym is null, skip deopt");
return; return;
} }
if (!class_linker_) {
LOGE("class_linker_ is null, skip deopt");
return;
}
void *reflected_method = env->FromReflectedMethod(method); void *reflected_method = env->FromReflectedMethod(method);
if (std::find(deoptedMethods.begin(), deoptedMethods.end(), reflected_method) != if (std::find(deoptedMethods.begin(), deoptedMethods.end(), reflected_method) !=
deoptedMethods.end()) { deoptedMethods.end()) {
LOGD("method %p has been deopted before, skip...", reflected_method); LOGD("method %p has been deopted before, skip...", reflected_method);
return; return;
} }
LOGD("deoptimize method: %p", reflected_method); LOGD("deoptimizing method: %p", reflected_method);
(*deoptMethod)(instru_, reflected_method); (*deoptMethod)(class_linker_, reflected_method);
deoptedMethods.push_back(reflected_method); deoptedMethods.push_back(reflected_method);
LOGD("deoptimize method done: %p"); LOGD("method deoptimized: %p", reflected_method);
} }
void hookRuntime(int api_level, void *artHandle, void (*hookFun)(void *, void *, void **)) { void hookRuntime(int api_level, void *artHandle, void (*hookFun)(void *, void *, void **)) {
@ -249,7 +252,6 @@ void getSuspendSyms(int api_level, void *artHandle, void (*hookFun)(void *, void
LOGI("heapPreFork hooked."); LOGI("heapPreFork hooked.");
} }
} }
if (api_level >= ANDROID_N) { if (api_level >= ANDROID_N) {
suspendAll = reinterpret_cast<void (*)(ScopedSuspendAll *, const char *, bool)>(dlsym( suspendAll = reinterpret_cast<void (*)(ScopedSuspendAll *, const char *, bool)>(dlsym(
artHandle, artHandle,