Try to fix x86 crash caused by native bridge
This commit is contained in:
parent
a104684126
commit
258e10337d
|
|
@ -1,36 +0,0 @@
|
||||||
package org.lsposed.lspatch.appstub;
|
|
||||||
|
|
||||||
import android.app.Application;
|
|
||||||
import android.content.Context;
|
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
|
|
||||||
public class LSPApplicationStub extends Application {
|
|
||||||
|
|
||||||
private static byte[] dex = null;
|
|
||||||
|
|
||||||
static {
|
|
||||||
try (var is = LSPApplicationStub.class.getClassLoader().getResourceAsStream("assets/lsp");
|
|
||||||
var os = new ByteArrayOutputStream()) {
|
|
||||||
byte[] buffer = new byte[8192];
|
|
||||||
int n;
|
|
||||||
while (-1 != (n = is.read(buffer))) {
|
|
||||||
os.write(buffer, 0, n);
|
|
||||||
}
|
|
||||||
dex = os.toByteArray();
|
|
||||||
} catch (Throwable e) {
|
|
||||||
android.util.Log.e("LSPatch", "load dex error", e);
|
|
||||||
}
|
|
||||||
System.loadLibrary("lspd");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreate() {
|
|
||||||
super.onCreate();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void attachBaseContext(Context base) {
|
|
||||||
super.attachBaseContext(base);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -28,6 +28,7 @@ public class LSPAppComponentFactoryStub extends AppComponentFactory {
|
||||||
private static final String ORIGINAL_APP_COMPONENT_FACTORY_ASSET_PATH = "assets/original_app_component_factory.ini";
|
private static final String ORIGINAL_APP_COMPONENT_FACTORY_ASSET_PATH = "assets/original_app_component_factory.ini";
|
||||||
|
|
||||||
private ClassLoader appClassLoader = null;
|
private ClassLoader appClassLoader = null;
|
||||||
|
private ClassLoader lspClassLoader = null;
|
||||||
private ClassLoader baseClassLoader = null;
|
private ClassLoader baseClassLoader = null;
|
||||||
private AppComponentFactory originalAppComponentFactory = null;
|
private AppComponentFactory originalAppComponentFactory = null;
|
||||||
|
|
||||||
|
|
@ -37,8 +38,7 @@ public class LSPAppComponentFactoryStub extends AppComponentFactory {
|
||||||
**/
|
**/
|
||||||
private void initOriginalAppComponentFactory(ApplicationInfo aInfo) {
|
private void initOriginalAppComponentFactory(ApplicationInfo aInfo) {
|
||||||
final String cacheApkPath = aInfo.dataDir + "/cache/origin_apk.bin";
|
final String cacheApkPath = aInfo.dataDir + "/cache/origin_apk.bin";
|
||||||
final String originalAppComponentFactoryClass =
|
final String originalAppComponentFactoryClass = FileUtils.readTextFromInputStream(baseClassLoader.getResourceAsStream(ORIGINAL_APP_COMPONENT_FACTORY_ASSET_PATH));
|
||||||
FileUtils.readTextFromInputStream(baseClassLoader.getResourceAsStream(ORIGINAL_APP_COMPONENT_FACTORY_ASSET_PATH));
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
try (InputStream inputStream = baseClassLoader.getResourceAsStream(ORIGINAL_APK_ASSET_PATH)) {
|
try (InputStream inputStream = baseClassLoader.getResourceAsStream(ORIGINAL_APK_ASSET_PATH)) {
|
||||||
|
|
@ -46,10 +46,15 @@ public class LSPAppComponentFactoryStub extends AppComponentFactory {
|
||||||
} catch (FileAlreadyExistsException ignored) {
|
} catch (FileAlreadyExistsException ignored) {
|
||||||
}
|
}
|
||||||
appClassLoader = new PathClassLoader(cacheApkPath, aInfo.nativeLibraryDir, baseClassLoader.getParent());
|
appClassLoader = new PathClassLoader(cacheApkPath, aInfo.nativeLibraryDir, baseClassLoader.getParent());
|
||||||
if (originalAppComponentFactoryClass == null || originalAppComponentFactoryClass.isEmpty())
|
|
||||||
originalAppComponentFactory = new AppComponentFactory();
|
try {
|
||||||
else
|
|
||||||
originalAppComponentFactory = (AppComponentFactory) appClassLoader.loadClass(originalAppComponentFactoryClass).newInstance();
|
originalAppComponentFactory = (AppComponentFactory) appClassLoader.loadClass(originalAppComponentFactoryClass).newInstance();
|
||||||
|
} catch (ClassNotFoundException | NullPointerException ignored) {
|
||||||
|
if (originalAppComponentFactoryClass != null && !originalAppComponentFactoryClass.isEmpty())
|
||||||
|
Log.w(TAG, "Original AppComponentFactory not found");
|
||||||
|
originalAppComponentFactory = new AppComponentFactory();
|
||||||
|
}
|
||||||
|
|
||||||
Log.d(TAG, "Instantiate original AppComponentFactory: " + originalAppComponentFactory);
|
Log.d(TAG, "Instantiate original AppComponentFactory: " + originalAppComponentFactory);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
Log.e(TAG, "initOriginalAppComponentFactory", e);
|
Log.e(TAG, "initOriginalAppComponentFactory", e);
|
||||||
|
|
@ -59,6 +64,9 @@ public class LSPAppComponentFactoryStub extends AppComponentFactory {
|
||||||
@Override
|
@Override
|
||||||
public ClassLoader instantiateClassLoader(ClassLoader cl, ApplicationInfo aInfo) {
|
public ClassLoader instantiateClassLoader(ClassLoader cl, ApplicationInfo aInfo) {
|
||||||
baseClassLoader = cl;
|
baseClassLoader = cl;
|
||||||
|
var apkPath = baseClassLoader.getResource("AndroidManifest.xml").getPath();
|
||||||
|
apkPath = apkPath.substring(5, apkPath.lastIndexOf('!'));
|
||||||
|
lspClassLoader = new PathClassLoader(apkPath, null, null);
|
||||||
initOriginalAppComponentFactory(aInfo);
|
initOriginalAppComponentFactory(aInfo);
|
||||||
Log.d(TAG, "baseClassLoader is " + baseClassLoader);
|
Log.d(TAG, "baseClassLoader is " + baseClassLoader);
|
||||||
Log.d(TAG, "appClassLoader is " + appClassLoader);
|
Log.d(TAG, "appClassLoader is " + appClassLoader);
|
||||||
|
|
@ -67,7 +75,7 @@ public class LSPAppComponentFactoryStub extends AppComponentFactory {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Application instantiateApplication(ClassLoader cl, String className) throws IllegalAccessException, InstantiationException, ClassNotFoundException {
|
public Application instantiateApplication(ClassLoader cl, String className) throws IllegalAccessException, InstantiationException, ClassNotFoundException {
|
||||||
baseClassLoader.loadClass(PROXY_APPLICATION).newInstance();
|
lspClassLoader.loadClass(PROXY_APPLICATION).newInstance();
|
||||||
return originalAppComponentFactory.instantiateApplication(cl, className);
|
return originalAppComponentFactory.instantiateApplication(cl, className);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,15 @@
|
||||||
package org.lsposed.lspatch.appstub;
|
package org.lsposed.lspatch.appstub;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
import android.app.Application;
|
import android.app.Application;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
|
||||||
|
@SuppressLint("UnsafeDynamicallyLoadedCode")
|
||||||
public class LSPApplicationStub extends Application {
|
public class LSPApplicationStub extends Application {
|
||||||
|
|
||||||
private static byte[] dex = null;
|
private static byte[] dex = null;
|
||||||
|
|
@ -19,9 +24,16 @@ public class LSPApplicationStub extends Application {
|
||||||
}
|
}
|
||||||
dex = os.toByteArray();
|
dex = os.toByteArray();
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
android.util.Log.e("LSPatch", "load dex error", e);
|
Log.e("LSPatch", "load dex error", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
try (var br = new BufferedReader(new InputStreamReader(Runtime.getRuntime().exec("getprop ro.product.cpu.abi").getInputStream()))) {
|
||||||
|
String arch = br.readLine();
|
||||||
|
String path = LSPApplicationStub.class.getClassLoader().getResource("assets/lib/" + arch + "/liblspd.so").getPath().substring(5);
|
||||||
|
System.load(path);
|
||||||
|
} catch (Throwable e) {
|
||||||
|
Log.e("LSPatch", "load lspd error", e);
|
||||||
}
|
}
|
||||||
System.loadLibrary("lspd");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,6 @@ import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.jar.JarFile;
|
import java.util.jar.JarFile;
|
||||||
|
|
||||||
public class LSPatch {
|
public class LSPatch {
|
||||||
|
|
@ -97,6 +96,12 @@ public class LSPatch {
|
||||||
"x86_64"
|
"x86_64"
|
||||||
));
|
));
|
||||||
|
|
||||||
|
private static final ZFileOptions Z_FILE_OPTIONS = new ZFileOptions().setAlignmentRule(AlignmentRules.compose(
|
||||||
|
AlignmentRules.constantForSuffix(".so", 4096),
|
||||||
|
AlignmentRules.constantForSuffix(RESOURCES_ARSC, 4),
|
||||||
|
AlignmentRules.constantForSuffix(ORIGINAL_APK_ASSET_PATH, 4096)
|
||||||
|
));
|
||||||
|
|
||||||
private static JCommander jCommander;
|
private static JCommander jCommander;
|
||||||
|
|
||||||
public static void main(String... args) throws IOException {
|
public static void main(String... args) throws IOException {
|
||||||
|
|
@ -154,14 +159,7 @@ public class LSPatch {
|
||||||
|
|
||||||
System.out.println("Parsing original apk...");
|
System.out.println("Parsing original apk...");
|
||||||
|
|
||||||
final ZFileOptions zFileOptions = new ZFileOptions();
|
try (ZFile zFile = ZFile.openReadWrite(tmpApk, Z_FILE_OPTIONS)) {
|
||||||
|
|
||||||
final var alignmentRule = AlignmentRules.compose(
|
|
||||||
AlignmentRules.constantForSuffix(RESOURCES_ARSC, 4),
|
|
||||||
AlignmentRules.constantForSuffix(ORIGINAL_APK_ASSET_PATH, 4096)
|
|
||||||
);
|
|
||||||
zFileOptions.setAlignmentRule(alignmentRule);
|
|
||||||
try (ZFile zFile = ZFile.openReadWrite(tmpApk, zFileOptions)) {
|
|
||||||
// copy origin apk to assets
|
// copy origin apk to assets
|
||||||
zFile.add(ORIGINAL_APK_ASSET_PATH, new FileInputStream(srcApkFile), false);
|
zFile.add(ORIGINAL_APK_ASSET_PATH, new FileInputStream(srcApkFile), false);
|
||||||
|
|
||||||
|
|
@ -225,36 +223,13 @@ public class LSPatch {
|
||||||
throw new PatchError("Error when saving application name: " + e);
|
throw new PatchError("Error when saving application name: " + e);
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy so and dex files into the unzipped apk
|
|
||||||
Set<String> apkArchs = new HashSet<>();
|
|
||||||
|
|
||||||
if (verbose)
|
|
||||||
System.out.println("Search target apk library arch..");
|
|
||||||
for (StoredEntry storedEntry : zFile.entries()) {
|
|
||||||
var name = storedEntry.getCentralDirectoryHeader().getName();
|
|
||||||
if (name.startsWith("lib/") && name.length() >= 5) {
|
|
||||||
var arch = name.substring(4, name.indexOf('/', 5));
|
|
||||||
apkArchs.add(arch);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (apkArchs.isEmpty()) {
|
|
||||||
apkArchs.addAll(APK_LIB_PATH_ARRAY);
|
|
||||||
}
|
|
||||||
|
|
||||||
apkArchs.removeIf((arch) -> {
|
|
||||||
if (!APK_LIB_PATH_ARRAY.contains(arch) && !arch.equals("armeabi")) {
|
|
||||||
System.err.println("Warning: unsupported arch " + arch + ". Skipping...");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
System.out.println("Adding native lib..");
|
System.out.println("Adding native lib..");
|
||||||
|
|
||||||
for (String arch : apkArchs) {
|
// copy so and dex files into the unzipped apk
|
||||||
// lib/armeabi-v7a -> armeabi-v7a
|
// do not put liblspd.so into apk!lib because x86 native bridge causes crash
|
||||||
String entryName = "lib/" + arch + "/liblspd.so";
|
for (String arch : APK_LIB_PATH_ARRAY) {
|
||||||
|
String entryName = "assets/lib/" + arch + "/liblspd.so";
|
||||||
try (var is = getClass().getClassLoader().getResourceAsStream("assets/so/" + (arch.equals("armeabi") ? "armeabi-v7a" : arch) + "/liblspd.so")) {
|
try (var is = getClass().getClassLoader().getResourceAsStream("assets/so/" + (arch.equals("armeabi") ? "armeabi-v7a" : arch) + "/liblspd.so")) {
|
||||||
zFile.add(entryName, is, false); // no compress for so
|
zFile.add(entryName, is, false); // no compress for so
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue