[core] Refine dexmaker cache stategy for YAHFA (#187)

* [core] Refine dexmaker cache stategy for YAHFA

* Delete old when old cache is invalid
This commit is contained in:
LoveSy 2021-02-24 22:13:24 +08:00 committed by GitHub
parent d0bd6c1be3
commit cc0afb03e8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 34 additions and 25 deletions

View File

@ -150,7 +150,6 @@ public class ConfigManager {
// for system server, cache is not yet ready, we need to query database for it
public boolean shouldSkipSystemServer() {
try (Cursor cursor = db.query("scope INNER JOIN modules ON scope.mid = modules.mid", new String[]{"modules.mid"}, "app_pkg_name=? AND enabled=1", new String[]{"android"}, null, null, null)) {
Log.e(TAG, "ZHEER2");
return cursor == null || !cursor.moveToNext();
}
}

View File

@ -42,7 +42,6 @@ public class LSPosedService extends ILSPosedService.Stub {
return null;
}
if (uid == 1000 && processName.equals("android")) {
Log.e(TAG, "ZHEER");
if (ConfigManager.getInstance().shouldSkipSystemServer())
return null;
else

View File

@ -155,45 +155,54 @@ public class HookerDexMaker {
@SuppressWarnings("ResultOfMethodCallIgnored")
@TargetApi(Build.VERSION_CODES.O)
private void doMake(String hookedClassName) throws Exception {
ClassLoader loader = null;
Class<?> hookClass = null;
// Generate a Hooker class.
String className = CLASS_NAME_PREFIX;
boolean usedCache = false;
if (canCache) {
try {
mDexMaker = new DexMaker();
// className is also used as dex file name
// so it should be different from each other
String suffix = DexMakerUtils.getSha1Hex(mMember.toString());
className = className + suffix;
String dexFileName = className + ".jar";
File dexFile = new File(serviceClient.getCachePath(dexFileName));
if (!dexFile.exists()) {
mDexMaker = new DexMaker();
// className is also used as dex file name
// so it should be different from each other
String suffix = DexMakerUtils.getSha1Hex(mMember.toString());
className = className + suffix;
String dexFileName = className + ".jar";
File dexFile = new File(serviceClient.getCachePath(dexFileName));
if (dexFile.exists()) {
try {
// if file exists, reuse it and skip generating
DexLog.d("Generating " + dexFileName);
DexLog.d("Using cache " + dexFileName);
ClassLoader loader = mDexMaker.loadClassDirect(mAppClassLoader, dexFile.getParentFile(), dexFileName);
hookClass = Class.forName(className.replace("/", "."), true, loader);
} catch (Throwable ignored) {
}
}
if (hookClass == null) {
try {
DexLog.d("cache not hit, generating " + dexFileName);
doGenerate(className);
loader = mDexMaker.generateAndLoad(mAppClassLoader, new File(serviceClient.getCachePath("")), dexFileName, false);
ClassLoader loader = mDexMaker.generateAndLoad(mAppClassLoader, dexFile.getParentFile(), dexFileName, true);
dexFile.setWritable(true, false);
dexFile.setReadable(true, false);
} else {
DexLog.d("Using cache " + dexFileName);
loader = mDexMaker.loadClassDirect(mAppClassLoader, new File(serviceClient.getCachePath("")), dexFileName);
hookClass = Class.forName(className.replace("/", "."), true, loader);
} catch (Throwable ignored) {
}
usedCache = true;
} catch (Throwable ignored) {}
}
}
if (!usedCache) {
if (hookClass == null) {
// do everything in memory
DexLog.d("Generating in memory");
DexLog.d("Falling back to generate in memory");
if (BuildConfig.DEBUG)
className = className + hookedClassName.replace(".", "/");
mDexMaker = new DexMaker();
doGenerate(className);
byte[] dexBytes = mDexMaker.generate();
loader = new InMemoryDexClassLoader(ByteBuffer.wrap(dexBytes), mAppClassLoader);
ClassLoader loader = new InMemoryDexClassLoader(ByteBuffer.wrap(dexBytes), mAppClassLoader);
hookClass = Class.forName(className.replace("/", "."), true, loader);
}
Class<?> hookClass = Class.forName(className.replace("/", "."), true, loader);
if (hookClass == null) {
DexLog.e("Unable to generate hooker class. This should not happen. Skipping...");
return;
}
// Execute our newly-generated code in-process.
Method backupMethod = hookClass.getMethod(METHOD_NAME_BACKUP, mActualParameterTypes);
mHooker = new LspHooker(mHookInfo, mMember, backupMethod);
@ -212,7 +221,9 @@ public class HookerDexMaker {
generateHookMethod();
}
public LspHooker getHooker() {return mHooker;}
public LspHooker getHooker() {
return mHooker;
}
private void generateFields() {
mHookerFieldId = mHookerTypeId.getField(hookerTypeId, FIELD_NAME_HOOKER);