diff --git a/Bridge/src/main/java/com/elderdrivers/riru/xposed/entry/Router.java b/Bridge/src/main/java/com/elderdrivers/riru/xposed/entry/Router.java index 73ef995f..7d358fb5 100644 --- a/Bridge/src/main/java/com/elderdrivers/riru/xposed/entry/Router.java +++ b/Bridge/src/main/java/com/elderdrivers/riru/xposed/entry/Router.java @@ -2,15 +2,19 @@ package com.elderdrivers.riru.xposed.entry; import android.text.TextUtils; -import com.elderdrivers.riru.xposed.config.InstallerChooser; +import com.elderdrivers.riru.xposed.Main; import com.elderdrivers.riru.xposed.core.HookMain; import com.elderdrivers.riru.xposed.entry.bootstrap.AppBootstrapHookInfo; import com.elderdrivers.riru.xposed.entry.bootstrap.SysBootstrapHookInfo; import com.elderdrivers.riru.xposed.entry.bootstrap.SysInnerHookInfo; import com.elderdrivers.riru.xposed.entry.hooker.SystemMainHooker; +import com.elderdrivers.riru.xposed.util.InlinedMethodCallers; import com.elderdrivers.riru.xposed.util.Utils; +import java.util.Arrays; + import de.robv.android.xposed.XposedBridge; +import de.robv.android.xposed.XposedHelpers; import de.robv.android.xposed.XposedInit; public class Router { diff --git a/Bridge/src/main/java/com/elderdrivers/riru/xposed/entry/hooker/SystemMainHooker.java b/Bridge/src/main/java/com/elderdrivers/riru/xposed/entry/hooker/SystemMainHooker.java index 11f81373..1f51c3d2 100644 --- a/Bridge/src/main/java/com/elderdrivers/riru/xposed/entry/hooker/SystemMainHooker.java +++ b/Bridge/src/main/java/com/elderdrivers/riru/xposed/entry/hooker/SystemMainHooker.java @@ -4,6 +4,7 @@ import android.app.ActivityThread; import com.elderdrivers.riru.common.KeepMembers; import com.elderdrivers.riru.xposed.entry.Router; +import com.elderdrivers.riru.xposed.util.PrebuiltMethodsDeopter; import de.robv.android.xposed.XposedBridge; @@ -30,6 +31,8 @@ public class SystemMainHooker implements KeepMembers { try { // get system_server classLoader systemServerCL = Thread.currentThread().getContextClassLoader(); + // deopt methods in SYSTEMSERVERCLASSPATH + PrebuiltMethodsDeopter.deoptSystemServerMethods(systemServerCL); Router.startSystemServerHook(); } catch (Throwable t) { logE("error when hooking systemMain", t); diff --git a/Bridge/src/main/java/com/elderdrivers/riru/xposed/proxy/yahfa/BlackWhiteListProxy.java b/Bridge/src/main/java/com/elderdrivers/riru/xposed/proxy/yahfa/BlackWhiteListProxy.java index f975373d..d361b38a 100644 --- a/Bridge/src/main/java/com/elderdrivers/riru/xposed/proxy/yahfa/BlackWhiteListProxy.java +++ b/Bridge/src/main/java/com/elderdrivers/riru/xposed/proxy/yahfa/BlackWhiteListProxy.java @@ -3,6 +3,7 @@ package com.elderdrivers.riru.xposed.proxy.yahfa; import com.elderdrivers.riru.xposed.Main; import com.elderdrivers.riru.xposed.config.ConfigManager; import com.elderdrivers.riru.xposed.entry.Router; +import com.elderdrivers.riru.xposed.util.PrebuiltMethodsDeopter; import static com.elderdrivers.riru.xposed.util.FileUtils.getDataPathPrefix; @@ -13,8 +14,11 @@ public class BlackWhiteListProxy { String niceName, int[] fdsToClose, int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir) { + // always enter here, make sure secondary zygote's modules is loaded only once + // when isDynamicModulesMode is not on final boolean isDynamicModulesMode = Main.isDynamicModulesEnabled(); ConfigManager.setDynamicModulesMode(isDynamicModulesMode); + PrebuiltMethodsDeopter.deoptBootMethods(); // do it once for secondary zygote if (!isDynamicModulesMode) { Router.loadModulesSafely(); Main.closeFilesBeforeForkNative(); @@ -22,6 +26,8 @@ public class BlackWhiteListProxy { } public static void forkAndSpecializePost(int pid, String appDataDir) { + // when this process is in white list or not in black list + // installBootstrapHooks -> loadModules if needed final boolean isDynamicModulesMode = Main.isDynamicModulesEnabled(); if (!isDynamicModulesMode) { Main.reopenFilesAfterForkNative(); @@ -36,8 +42,14 @@ public class BlackWhiteListProxy { public static void forkSystemServerPre(int uid, int gid, int[] gids, int debugFlags, int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) { + // we always enter here whether black/white list is on or not final boolean isDynamicModulesMode = Main.isDynamicModulesEnabled(); ConfigManager.setDynamicModulesMode(isDynamicModulesMode); + PrebuiltMethodsDeopter.deoptBootMethods(); // do it once for main zygote + // we never install bootstrap hooks here in black/white list mode + // because installed hooks would be propagated to all child processes of main zygote + // hence we cannot install hooks for processes like com.android.phone process who are + // not from forkAndSpecialize as a side effect if (!isDynamicModulesMode) { Router.loadModulesSafely(); Main.closeFilesBeforeForkNative(); @@ -45,6 +57,8 @@ public class BlackWhiteListProxy { } public static void forkSystemServerPost(int pid) { + // should only here when system_server is in white list or not in black list + // installBootstrapHooks -> loadModules if needed final boolean isDynamicModulesMode = Main.isDynamicModulesEnabled(); if (!isDynamicModulesMode) { Main.reopenFilesAfterForkNative(); diff --git a/Bridge/src/main/java/com/elderdrivers/riru/xposed/proxy/yahfa/NormalProxy.java b/Bridge/src/main/java/com/elderdrivers/riru/xposed/proxy/yahfa/NormalProxy.java index 462e9db2..20988054 100644 --- a/Bridge/src/main/java/com/elderdrivers/riru/xposed/proxy/yahfa/NormalProxy.java +++ b/Bridge/src/main/java/com/elderdrivers/riru/xposed/proxy/yahfa/NormalProxy.java @@ -4,6 +4,7 @@ import com.elderdrivers.riru.xposed.Main; import com.elderdrivers.riru.xposed.config.ConfigManager; import com.elderdrivers.riru.xposed.dexmaker.DynamicBridge; import com.elderdrivers.riru.xposed.entry.Router; +import com.elderdrivers.riru.xposed.util.PrebuiltMethodsDeopter; import static com.elderdrivers.riru.xposed.util.FileUtils.getDataPathPrefix; @@ -17,6 +18,7 @@ public class NormalProxy { final boolean isDynamicModulesMode = Main.isDynamicModulesEnabled(); Main.appDataDir = appDataDir; ConfigManager.setDynamicModulesMode(isDynamicModulesMode); + PrebuiltMethodsDeopter.deoptBootMethods(); // do it once for secondary zygote Router.prepare(false); // install bootstrap hooks for secondary zygote Router.installBootstrapHooks(false); @@ -40,6 +42,7 @@ public class NormalProxy { Main.appDataDir = getDataPathPrefix() + "android"; ConfigManager.setDynamicModulesMode(isDynamicModulesMode); Router.prepare(true); + PrebuiltMethodsDeopter.deoptBootMethods(); // do it once for main zygote // install bootstrap hooks for main zygote as early as possible // in case we miss some processes not forked via forkAndSpecialize // for instance com.android.phone diff --git a/Bridge/src/main/java/com/elderdrivers/riru/xposed/util/InlinedMethodCallers.java b/Bridge/src/main/java/com/elderdrivers/riru/xposed/util/InlinedMethodCallers.java new file mode 100644 index 00000000..eb8a29cc --- /dev/null +++ b/Bridge/src/main/java/com/elderdrivers/riru/xposed/util/InlinedMethodCallers.java @@ -0,0 +1,49 @@ +package com.elderdrivers.riru.xposed.util; + +import java.util.HashMap; + +/** + * Providing a whitelist of methods which are the callers of the target methods we want to hook. + * Because the target methods are inlined into the callers, we deoptimize the callers to + * run in intercept mode to make target methods hookable. + *
+ * Only for methods which are included in pre-compiled framework codes.
+ * TODO recompile system apps and priv-apps since their original dex files are available
+ */
+public class InlinedMethodCallers {
+
+ public static final String KEY_BOOT_IMAGE = "boot_image";
+ public static final String KEY_SYSTEM_SERVER = "system_server";
+
+ /**
+ * Key should be {@link #KEY_BOOT_IMAGE}, {@link #KEY_SYSTEM_SERVER}, or a package name
+ * of system apps or priv-apps i.e. com.android.systemui
+ */
+ private static final HashMap