Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimize dexmaker for yahfa #759

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ private static boolean isFileExists(String path) {

public static native String getPrefsPath(String suffix);

public static native String getCachePath(String suffix);

public static native String getBaseConfigPath();

public static native String getDataPathPrefix();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ private void forkPostCommon(int pid, boolean isSystem, String appDataDir, String
mRouter.initResourcesHook();
mRouter.prepare(isSystem);
PrebuiltMethodsDeopter.deoptBootMethods(); // do it once for secondary zygote
mRouter.installBootstrapHooks(isSystem);
ConfigManager.appDataDir = appDataDir;
ConfigManager.niceName = niceName;
mRouter.installBootstrapHooks(isSystem);
XposedInit.prefsBasePath = ConfigManager.getPrefsPath("");
mRouter.onEnterChildProcess();
Utils.logI("Loading modules for " + niceName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,6 @@ public static String getPackageName(String dataDir) {
}

public static String getDataPathPrefix() {
return ConfigManager.getDataPathPrefix();
return ConfigManager.getDataPathPrefix() + "/";
}
}
4 changes: 4 additions & 0 deletions edxp-core/src/main/cpp/main/src/config_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ namespace edxp {
return misc_path_ / "framework" / suffix;
}

inline static auto GetCachePath(const std::string &suffix = {}) {
return misc_path_ / "cache" / suffix;
yujincheng08 marked this conversation as resolved.
Show resolved Hide resolved
}

inline static auto GetLibSandHookName() {
if constexpr(edxp::is64)
return GetFrameworkPath("lib64/libsandhook.edxp.so");
Expand Down
9 changes: 9 additions & 0 deletions edxp-core/src/main/cpp/main/src/jni/edxp_config_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,13 @@ namespace edxp {
return env->NewStringUTF(result.c_str());
}

static jstring ConfigManager_getCachePath(JNI_START, jstring jSuffix) {
const char *suffix = env->GetStringUTFChars(jSuffix, JNI_FALSE);
auto result = ConfigManager::GetCachePath(suffix);
env->ReleaseStringUTFChars(jSuffix, suffix);
return env->NewStringUTF(result.c_str());
}

static jstring ConfigManager_getBaseConfigPath(JNI_START) {
auto result = ConfigManager::GetInstance()->GetBaseConfigPath();
return env->NewStringUTF(result.c_str());
Expand Down Expand Up @@ -80,6 +87,8 @@ namespace edxp {
"(Ljava/lang/String;)Ljava/lang/String;"),
NATIVE_METHOD(ConfigManager, getPrefsPath,
"(Ljava/lang/String;)Ljava/lang/String;"),
NATIVE_METHOD(ConfigManager, getCachePath,
"(Ljava/lang/String;)Ljava/lang/String;"),
NATIVE_METHOD(ConfigManager, getBaseConfigPath,"()Ljava/lang/String;"),
NATIVE_METHOD(ConfigManager, getModulesList, "()Ljava/lang/String;"),
};
Expand Down
3 changes: 3 additions & 0 deletions edxp-core/template_override/customize.sh
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,9 @@ if [[ "${VARIANT}" == "SandHook" ]]; then
fi
set_perm_recursive /data/misc/$MISC_PATH/framework root root 0755 0644 "u:object_r:magisk_file:s0" || abortC "! ${LANG_CUST_ERR_PERM}"

mkdir -p /data/misc/$MISC_PATH/cache
set_perm /data/misc/$MISC_PATH/cache root root 0777 "u:object_r:magisk_file:s0" || abortC "! ${LANG_CUST_ERR_PERM}"

mv "${MODPATH}/system/lib/libriru_edxp.so" "${MODPATH}/system/lib/${LIB_RIRU_EDXP}"
if [[ "${IS64BIT}" == true ]]; then
mv "${MODPATH}/system/lib64/libriru_edxp.so" "${MODPATH}/system/lib64/${LIB_RIRU_EDXP}"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
package com.elderdrivers.riru.edxp.yahfa.dexmaker;

import android.app.AndroidAppHelper;
import android.os.Build;
import android.text.TextUtils;

import com.elderdrivers.riru.edxp.config.ConfigManager;
import com.elderdrivers.riru.edxp.util.Utils;

import java.io.File;
import java.security.MessageDigest;
import java.util.HashMap;
import java.util.Map;
Expand All @@ -16,19 +14,14 @@

public class DexMakerUtils {

private static final boolean IN_MEMORY_DEX_ELIGIBLE = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;
public static boolean canCache = true;

public static boolean shouldUseInMemoryHook() {
if (!IN_MEMORY_DEX_ELIGIBLE) {
return false;
}
String packageName = AndroidAppHelper.currentPackageName();
if (TextUtils.isEmpty(packageName)) { //default to true
DexLog.w("packageName is empty, processName=" + ConfigManager.appProcessName
+ ", appDataDir=" + ConfigManager.appDataDir);
return true;
static {
File cacheDir = new File(ConfigManager.getCachePath(""));
if(!cacheDir.canRead() || !cacheDir.canWrite()) {
Utils.logW("Cache disabled");
canCache = false;
}
return !ConfigManager.shouldUseCompatMode(packageName);
}

public static void autoBoxIfNecessary(Code code, Local<Object> target, Local source) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,14 @@
import java.util.HashMap;
import java.util.concurrent.atomic.AtomicBoolean;

import de.robv.android.xposed.EdHooker;
import de.robv.android.xposed.XposedBridge;

import static com.elderdrivers.riru.edxp.util.FileUtils.getDataPathPrefix;
import static com.elderdrivers.riru.edxp.util.FileUtils.getPackageName;
import static com.elderdrivers.riru.edxp.util.ProcessUtils.getCurrentProcessName;
import static com.elderdrivers.riru.edxp.yahfa.dexmaker.DexMakerUtils.shouldUseInMemoryHook;

public final class DynamicBridge {

private static final HashMap<Member, Method> hookedInfo = new HashMap<>();
private static final HashMap<Member, EdHooker> hookedInfo = new HashMap<>();
private static final HookerDexMaker dexMaker = new HookerDexMaker();
private static final AtomicBoolean dexPathInited = new AtomicBoolean(false);
private static File dexDir;
private static File dexOptDir;

/**
Expand All @@ -47,43 +42,16 @@ public static synchronized void hookMethod(Member hookMethod, XposedBridge.Addit
}

DexLog.d("start to generate class for: " + hookMethod);
long startTime = System.nanoTime();
try {
// for Android Oreo and later use InMemoryClassLoader
if (!shouldUseInMemoryHook()) {
setupDexCachePath();
}
dexMaker.start(hookMethod, additionalHookInfo,
hookMethod.getDeclaringClass().getClassLoader(), getDexDirPath());
hookedInfo.put(hookMethod, dexMaker.getCallBackupMethod());
hookMethod.getDeclaringClass().getClassLoader());
hookedInfo.put(hookMethod, dexMaker.getHooker());
} catch (Exception e) {
DexLog.e("error occur when generating dex. dexDir=" + dexDir, e);
}
}

private static String getDexDirPath() {
if (dexDir == null) {
return null;
}
return dexDir.getAbsolutePath();
}

private static void setupDexCachePath() {
// using file based DexClassLoader
if (!dexPathInited.compareAndSet(false, true)) {
return;
}
try {
// we always choose to use device encrypted storage data on android N and later
// in case some app is installing hooks before phone is unlocked
String fixedAppDataDir = getDataPathPrefix() + getPackageName(ConfigManager.appDataDir) + "/";
dexDir = new File(fixedAppDataDir, "/cache/edhookers/"
+ getCurrentProcessName(ConfigManager.appProcessName).replace(":", "_") + "/");
dexOptDir = new File(dexDir, "oat");
dexDir.mkdirs();
DexLog.d(ConfigManager.appProcessName + " deleting dir: " + dexOptDir.getAbsolutePath());
} catch (Throwable throwable) {
DexLog.e("error when init dex path", throwable);
DexLog.e("error occur when generating dex.", e);
}
long endTime = System.nanoTime();
DexLog.d("generated class for " + hookMethod + " in " + ((endTime-startTime) * 1.e-6) + "ms");
}

private static boolean checkMember(Member member) {
Expand All @@ -106,28 +74,11 @@ private static boolean checkMember(Member member) {

public static Object invokeOriginalMethod(Member method, Object thisObject, Object[] args)
throws InvocationTargetException, IllegalAccessException {
Method callBackup = hookedInfo.get(method);
if (callBackup == null) {
EdHooker hooker = hookedInfo.get(method);
if (hooker == null) {
throw new IllegalStateException("method not hooked, cannot call original method.");
}
if (!Modifier.isStatic(callBackup.getModifiers())) {
throw new IllegalStateException("original method is not static, something must be wrong!");
}
callBackup.setAccessible(true);
if (args == null) {
args = new Object[0];
}
final int argsSize = args.length;
if (Modifier.isStatic(method.getModifiers())) {
return callBackup.invoke(null, args);
} else {
Object[] newArgs = new Object[argsSize + 1];
newArgs[0] = thisObject;
for (int i = 1; i < newArgs.length; i++) {
newArgs[i] = args[i - 1];
}
return callBackup.invoke(null, newArgs);
}
return hooker.callBackup(thisObject, args);
}
}

Expand Down
Loading