Skip to content

Commit 047ad98

Browse files
authored
Fix dex2oat crash on Android 10 due to architecture mismatch (#521)
Previously, the daemon determined the architecture of the target `dex2oat` binary based on its own process architecture (`Process.is64Bit()`). On Android 10, `/apex/com.android.runtime/bin/dex2oat` is frequently a 32-bit binary, even on 64-bit devices. This caused the daemon to incorrectly treat the target as 64-bit and mount the 64-bit wrapper (`bin/dex2oat64`). Consequently, the wrapper attempted to execute the 32-bit binary using `linker64`, resulting in a crash: `error: "/apex/.../dex2oat" is 32-bit instead of 64-bit` This commit changes the logic to inspect the ELF header of the target binary. We now explicitly check `e_ident[EI_CLASS]` to determine if the file is 32-bit or 64-bit and assign it to the correct mounting slot. This ensures the 32-bit wrapper is mounted over 32-bit targets, preventing the linker mismatch.
1 parent 1436f69 commit 047ad98

1 file changed

Lines changed: 66 additions & 6 deletions

File tree

daemon/src/main/java/org/lsposed/lspd/service/Dex2OatService.java

Lines changed: 66 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040

4141
import java.io.File;
4242
import java.io.FileDescriptor;
43+
import java.io.FileInputStream;
4344
import java.io.IOException;
4445
import java.nio.file.Files;
4546
import java.nio.file.Paths;
@@ -67,15 +68,74 @@ private void openDex2oat(int id, String path) {
6768
}
6869
}
6970

71+
/**
72+
* Checks the ELF header of the target file.
73+
* If 32-bit -> Assigns to Index 0 (Release) or 1 (Debug).
74+
* If 64-bit -> Assigns to Index 2 (Release) or 3 (Debug).
75+
*/
76+
private void checkAndAddDex2Oat(String path) {
77+
if (path == null)
78+
return;
79+
File file = new File(path);
80+
if (!file.exists())
81+
return;
82+
83+
try (FileInputStream fis = new FileInputStream(file)) {
84+
byte[] header = new byte[5];
85+
if (fis.read(header) != 5)
86+
return;
87+
88+
// 1. Verify ELF Magic: 0x7F 'E' 'L' 'F'
89+
if (header[0] != 0x7F || header[1] != 'E' || header[2] != 'L' || header[3] != 'F') {
90+
return;
91+
}
92+
93+
// 2. Check Architecture (header[4]): 1 = 32-bit, 2 = 64-bit
94+
boolean is32Bit = (header[4] == 1);
95+
boolean is64Bit = (header[4] == 2);
96+
boolean isDebug = path.contains("dex2oatd");
97+
98+
int index = -1;
99+
100+
if (is32Bit) {
101+
index = isDebug ? 1 : 0; // Index 0/1 maps to r32/d32 in C++
102+
} else if (is64Bit) {
103+
index = isDebug ? 3 : 2; // Index 2/3 maps to r64/d64 in C++
104+
}
105+
106+
// 3. Assign to the detected slot
107+
if (index != -1 && dex2oatArray[index] == null) {
108+
dex2oatArray[index] = path;
109+
try {
110+
// Open the FD for the wrapper to use later
111+
fdArray[index] = Os.open(path, OsConstants.O_RDONLY, 0);
112+
Log.i(TAG, "Detected " + path + " as " + (is64Bit ? "64-bit" : "32-bit") + " -> Assigned Index "
113+
+ index);
114+
} catch (ErrnoException e) {
115+
Log.e(TAG, "Failed to open FD for " + path, e);
116+
dex2oatArray[index] = null;
117+
}
118+
}
119+
} catch (IOException e) {
120+
// File not readable, skip
121+
}
122+
}
123+
70124
public Dex2OatService() {
71125
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.Q) {
72-
openDex2oat(Process.is64Bit() ? 2 : 0, "/apex/com.android.runtime/bin/dex2oat");
73-
openDex2oat(Process.is64Bit() ? 3 : 1, "/apex/com.android.runtime/bin/dex2oatd");
126+
// Android 10: Check the standard path.
127+
// Logic will detect if it is 32-bit and put it in Index 0.
128+
checkAndAddDex2Oat("/apex/com.android.runtime/bin/dex2oat");
129+
checkAndAddDex2Oat("/apex/com.android.runtime/bin/dex2oatd");
130+
131+
// Check for explicit 64-bit paths (just in case)
132+
checkAndAddDex2Oat("/apex/com.android.runtime/bin/dex2oat64");
133+
checkAndAddDex2Oat("/apex/com.android.runtime/bin/dex2oatd64");
74134
} else {
75-
openDex2oat(0, "/apex/com.android.art/bin/dex2oat32");
76-
openDex2oat(1, "/apex/com.android.art/bin/dex2oatd32");
77-
openDex2oat(2, "/apex/com.android.art/bin/dex2oat64");
78-
openDex2oat(3, "/apex/com.android.art/bin/dex2oatd64");
135+
checkAndAddDex2Oat("/apex/com.android.art/bin/dex2oat32");
136+
checkAndAddDex2Oat("/apex/com.android.art/bin/dex2oatd32");
137+
checkAndAddDex2Oat("/apex/com.android.art/bin/dex2oat64");
138+
checkAndAddDex2Oat("/apex/com.android.art/bin/dex2oatd64");
79139
}
80140

81141
openDex2oat(4, "/data/adb/modules/zygisk_lsposed/bin/liboat_hook32.so");

0 commit comments

Comments
 (0)