Skip to content

Refactor dex2oat wrapper to solve long-standing issues - #515

Merged
JingMatrix merged 12 commits into
masterfrom
dex2oat
Jan 25, 2026
Merged

JingMatrix merged 12 commits into
masterfrom
dex2oat

Conversation

@JingMatrix

Copy link
Copy Markdown
Owner

Manual library path injection via LD_LIBRARY_PATH has become unreliable due to symbol mismatches in core libraries (e.g., libc++) between the system and APEX partitions. Recent updates to liblog and libbase (in Android 16) have resulted in missing symbols like __hash_memory or fmt when the ART APEX binaries are forced to load system-partition shims.

This commit switches the wrapper to execute the runtime APEX linker directly (/apex/com.android.runtime/bin/linker64). By passing the dex2oat binary to the linker via /proc/self/fd/, the linker can properly initialize internal namespaces and resolve dependencies from the correct APEX and bootstrap locations.

Changes:

  • Replace fexecve(stock_fd) with execve(apex_linker).
  • Remove manual LD_LIBRARY_PATH construction.
  • Update sepolicy to allow dex2oat to execute the system linker.

Manual library path injection via LD_LIBRARY_PATH has become unreliable due to symbol mismatches in core libraries (e.g., libc++) between the system and APEX partitions. Recent updates to liblog and libbase (in Android 16) have resulted in missing symbols like `__hash_memory` or `fmt` when the ART APEX binaries are forced to load system-partition shims.

This commit switches the wrapper to execute the runtime APEX linker directly (/apex/com.android.runtime/bin/linker64). By passing the dex2oat binary to the linker via /proc/self/fd/, the linker can properly initialize internal namespaces and resolve dependencies from the correct APEX and bootstrap locations.

Changes:
- Replace fexecve(stock_fd) with execve(apex_linker).
- Remove manual LD_LIBRARY_PATH construction.
- Update sepolicy to allow dex2oat to execute the system linker.
@JingMatrix

Copy link
Copy Markdown
Owner Author

@sekaiacg, @mineketchup, @grandpajive
Please test the latest CI builds to see if dex2oat related problems are solved.

In Release builds, libc uses SIMD (NEON) instructions. To achieve high throughput, the __memcpy_a53 routine reads memory in 16-byte or 32-byte chunks (using LDRD or VLD1).

We also enble debug logs to track potential issues.
@sekaiacg

sekaiacg commented Jan 23, 2026 •

Copy link
Copy Markdown

https://github.com/JingMatrix/LSPosed/actions/runs/21269130798

debug version:

logcat | grep dex2oat
01-23 10:10:42.006  2032  3127 V installd: Running /apex/com.android.art/bin/dex2oat64 in=base.apk out=/data/app/~~Tv3_PmACzMOFlGKA6X7myw==/com.bit747.clipboardfilter-ddprIDgpEy6elDAypQSSxw==/oat/arm64/base.odex
01-23 10:10:42.013 14264 14264 D LSPosedDex2Oat: dex2oat.cpp:94#int main(int, char **): dex2oat wrapper ppid=2032
01-23 10:10:42.014  2257  2458 D LSPosedDex2Oat: Sent fd of /apex/com.android.art/bin/dex2oat64
01-23 10:10:42.014 14264 14264 D LSPosedDex2Oat: dex2oat.cpp:123#int main(int, char **): sock: xgmesoa14so27j8nkfxu8cgok7q9pe23 6
01-23 10:10:42.014 14264 14264 D LSPosedDex2Oat: dex2oat.cpp:153#int main(int, char **): Executing via linker: /apex/com.android.runtime/bin/linker64 /proc/self/fd/6
01-23 10:10:42.031 14264 14264 V LSPlt   : match hook info /apex/com.android.art/bin/dex2oat64:19 72373f7000 72373f8000-e5000
01-23 10:10:42.031 14264 14264 V LSPlt   : match hook info /apex/com.android.art/bin/dex2oat64:19 72373f3000 72373f7000-e2000
01-23 10:10:42.031 14264 14264 V LSPlt   : match hook info /apex/com.android.art/bin/dex2oat64:19 7237339000 72373f3000-28000
01-23 10:10:42.031 14264 14264 V LSPlt   : match hook info /apex/com.android.art/bin/dex2oat64:19 7237311000 7237339000-0
01-23 10:10:42.101 14264 14264 I 6       : dex2oat took 67.582ms (52.467ms cpu) (threads: 6) arena alloc=0B (0B) java alloc=80KB (82128B) native alloc=2207KB (2260288B) free=500KB (512704B)

release version:

logcat | grep dex2oat                                                                                                 
01-23 10:01:02.348 13930 13930 F libc    : Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x7026600000 in tid 13930 (dex2oat), pid 13930 (dex2oat)
01-23 10:01:02.446 13985 13985 F DEBUG   : pid: 13930, tid: 13930, name: dex2oat  >>> /apex/com.android.runtime/bin/linker64 <<<
01-23 10:02:02.014  2045  2060 V installd: Running /apex/com.android.art/bin/dex2oat64 in=base.apk out=/data/app/~~VGAKTumQ5tCYmkhYMFahSw==/com.bit747.clipboardfilter-aOiYN9ihb3L82VInGSSsZA==/oat/arm64/base.odex
01-23 10:02:02.021 18146 18146 W dex2oat64: type=1400 audit(0.0:1884): avc: denied { read } for name="u:object_r:vendor_default_prop:s0" dev="tmpfs" ino=23805 scontext=u:r:dex2oat:s0 tcontext=u:object_r:vendor_default_prop:s0 tclass=file permissive=0
01-23 10:02:02.024 18146 18146 D LSPosedDex2Oat: dex2oat.cpp:94#int main(int, char **): dex2oat wrapper ppid=2045
01-23 10:02:02.024 18146 18146 D LSPosedDex2Oat: dex2oat.cpp:123#int main(int, char **): sock: m25nre2l86xwa97yz8xd2aute5wn5zb6 6
01-23 10:02:02.024 18146 18146 D LSPosedDex2Oat: dex2oat.cpp:153#int main(int, char **): Executing via linker: /apex/com.android.runtime/bin/linker64 /proc/self/fd/6
01-23 10:02:02.037 18146 18146 W linker64: type=1400 audit(0.0:1885): avc: denied { read } for name="u:object_r:vendor_default_prop:s0" dev="tmpfs" ino=23805 scontext=u:r:dex2oat:s0 tcontext=u:object_r:vendor_default_prop:s0 tclass=file permissive=0
01-23 10:02:02.125 18146 18146 F libc    : Fatal signal 11 (SIGSEGV), code 2 (SEGV_ACCERR), fault addr 0x6f91c00000 in tid 18146 (dex2oat), pid 18146 (dex2oat)
01-23 10:02:02.158 18156 18156 F DEBUG   : pid: 18146, tid: 18146, name: dex2oat  >>> /apex/com.android.runtime/bin/linker64 <<<

problem not solved.
log: LSPosed_2026-01-23T10_03_06.130294.zip
The problem only occurs in the release version.

It seems that the PLT return value could be wrong on certain devices for the debug build.
@JingMatrix

JingMatrix commented Jan 23, 2026 •

Copy link
Copy Markdown
Owner Author

It turns out that PLT hooks didn't return correctly the key_value_store size:

[ 2026-01-23T10:01:02.029    50315: 13930: 13930 D/LSPosedDex2Oat  ] dex2oat.cpp:94#int main(int, char **): dex2oat wrapper ppid=2045
[ 2026-01-23T10:01:02.030    50315: 13930: 13930 D/LSPosedDex2Oat  ] dex2oat.cpp:123#int main(int, char **): sock: m25nre2l86xwa97yz8xd2aute5wn5zb6 6
[ 2026-01-23T10:01:02.030    50315: 13930: 13930 D/LSPosedDex2Oat  ] dex2oat.cpp:153#int main(int, char **): Executing via linker: /apex/com.android.runtime/bin/linker64 /proc/self/fd/6
[ 2026-01-23T10:01:02.088    50315: 13930: 13930 D/LSPosedDex2Oat  ] oat_hook.cpp:125#void register_hook(dev_t, ino_t, const char *, void *, void **): RegisterHook: _ZNK3art9OatHeader20GetKeyValueStoreSizeEv, 0x70b3299620, 0x70b32a7fe0
[ 2026-01-23T10:01:02.088    50315: 13930: 13930 D/LSPosedDex2Oat  ] oat_hook.cpp:125#void register_hook(dev_t, ino_t, const char *, void *, void **): RegisterHook: _ZNK3art9OatHeader16GetKeyValueStoreEv, 0x70b3299914, 0x70b32a7fe8
[ 2026-01-23T10:01:02.346    50315: 13930: 13930 D/LSPosedDex2Oat  ] oat_hook.cpp:99#uint8_t *new__ZNK3art9OatHeader16GetKeyValueStoreEv(void *): OatHeader::GetKeyValueStore() called on object at 0xb4000070263a2000
[ 2026-01-23T10:01:02.346    50315: 13930: 13930 D/LSPosedDex2Oat  ] oat_hook.cpp:102#uint8_t *new__ZNK3art9OatHeader16GetKeyValueStoreEv(void *): KeyValueStore via hook: [addr: 0xb4000070263a2048, size: 2019913825]
[ 2026-01-23T10:01:02.346    50315: 13930: 13930 D/LSPosedDex2Oat  ] oat_hook.cpp:47#bool ModifyStoreInPlace(uint8_t *, uint32_t): Parameter found at offset 3041.
[ 2026-01-23T10:01:02.346    50315: 13930: 13930 D/LSPosedDex2Oat  ] oat_hook.cpp:69#bool ModifyStoreInPlace(uint8_t *, uint32_t): No padding found. Removing parameter and shifting memory.
[ 2026-01-23T10:01:02.348    50315: 13930: 13930 F/libc            ] Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x7026600000 in tid 13930 (dex2oat), pid 13930 (dex2oat)
[ 2026-01-23T10:01:02.446    50315: 13985: 13985 F/DEBUG           ] *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
[ 2026-01-23T10:01:02.446    50315: 13985: 13985 F/DEBUG           ] Build fingerprint: 'Xiaomi/cmi/cmi:13/TKQ1.221114.001/V816.0.5.0.TJACNXM:user/release-keys'
[ 2026-01-23T10:01:02.446    50315: 13985: 13985 F/DEBUG           ] Revision: '0'
[ 2026-01-23T10:01:02.446    50315: 13985: 13985 F/DEBUG           ] ABI: 'arm64'
[ 2026-01-23T10:01:02.446    50315: 13985: 13985 F/DEBUG           ] Timestamp: 2026-01-23 10:01:02.421029208+0800
[ 2026-01-23T10:01:02.446    50315: 13985: 13985 F/DEBUG           ] Process uptime: 1s
[ 2026-01-23T10:01:02.446    50315: 13985: 13985 F/DEBUG           ] ZygotePid: 1188
[ 2026-01-23T10:01:02.446    50315: 13985: 13985 F/DEBUG           ] Cmdline: /apex/com.android.runtime/bin/linker64 /proc/self/fd/6 --zip-fd=8 --zip-location=base.apk --oat-fd=9 --oat-location=/data/app/~~oY3DBxEHC-bevhBfubjiVg==/com.bit747.clipboardfilter-WymIdNvkzHPU2JnrHg6CLQ==/oat/arm64/base.odex --input-vdex-fd=-1 --output-vdex-fd=10 --profile-file-fd=12 --swap-fd=11 --classpath-dir=/data/app/~~oY3DBxEHC-bevhBfubjiVg==/com.bit747.clipboardfilter-WymIdNvkzHPU2JnrHg6CLQ== --class-loader-context=PCL[]{} --compact-dex-level=none --instruction-set=arm64 --instruction-set-features=default --instruction-set-variant=kryo300 --compiler-filter=speed-profile --compilation-reason=install --cpu-set=0,1,2,3,4,5,6,7 --max-image-block-size=524288 --resolve-startup-const-strings=true --generate-mini-debug-info --runtime-arg -Xtarget-sdk-version:30 --runtime-arg -Xhidden-api-policy:enabled -j6 --runtime-arg -Xms64m --runtime-arg -Xmx512m --inline-max-code-units=0
[ 2026-01-23T10:01:02.446    50315: 13985: 13985 F/DEBUG           ] pid: 13930, tid: 13930, name: dex2oat  >>> /apex/com.android.runtime/bin/linker64 <<<
[ 2026-01-23T10:01:02.446    50315: 13985: 13985 F/DEBUG           ] uid: 50315
[ 2026-01-23T10:01:02.446    50315: 13985: 13985 F/DEBUG           ] signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0000007026600000
[ 2026-01-23T10:01:02.446    50315: 13985: 13985 F/DEBUG           ]     x0  0000000000000001  x1  b400007026207050  x2  0000000000000002  x3  0fffffffffffffff
[ 2026-01-23T10:01:02.446    50315: 13985: 13985 F/DEBUG           ]     x4  0000000000000000  x5  0000000000000000  x6  2f323832301f1f2f  x7  7f7f7f7f7f7f7f7f
[ 2026-01-23T10:01:02.446    50315: 13985: 13985 F/DEBUG           ]     x8  0000000000000000  x9  782b14536e9a98a2  x10 00000000000000cf  x11 0000000000000001
[ 2026-01-23T10:01:02.446    50315: 13985: 13985 F/DEBUG           ]     x12 0000007fd81c4934  x13 0000000000000005  x14 0000000000000000  x15 00000070af87aa02
[ 2026-01-23T10:01:02.446    50315: 13985: 13985 F/DEBUG           ]     x16 0000000000000001  x17 00000070af945c88  x18 00000070b7138000  x19 0000000078657047
[ 2026-01-23T10:01:02.446    50315: 13985: 13985 F/DEBUG           ]     x20 b4000070265fffe6  x21 00000000783f90a9  x22 b40000709e9f90a9  x23 b4000070263a2c43
[ 2026-01-23T10:01:02.446    50315: 13985: 13985 F/DEBUG           ]     x24 00000070b32a7fd8  x25 0000000000000000  x26 0000000000000000  x27 b40000702622c500
[ 2026-01-23T10:01:02.446    50315: 13985: 13985 F/DEBUG           ]     x28 00000070b3701000  x29 0000007fd81c6e30
[ 2026-01-23T10:01:02.446    50315: 13985: 13985 F/DEBUG           ]     lr  00000070b3299b64  sp  0000007fd81c6db0  pc  00000070b3299b70  pst 0000000020001000
[ 2026-01-23T10:01:02.446    50315: 13985: 13985 F/DEBUG           ] backtrace:
[ 2026-01-23T10:01:02.446    50315: 13985: 13985 F/DEBUG           ]   NOTE: Function names and BuildId information is missing for some frames due
  NOTE: to unreadable libraries. For unwinds of apps, only shared libraries
  NOTE: found under the lib/ directory are readable.
  NOTE: On this device, run setenforce 0 to make the libraries readable.
  NOTE: Unreadable libraries:
  NOTE:   /data/adb/modules/zygisk_lsposed/bin/liboat_hook64.so
[ 2026-01-23T10:01:02.446    50315: 13985: 13985 F/DEBUG           ]       #00 pc 0000000000033b70  /data/adb/modules/zygisk_lsposed/bin/liboat_hook64.so

The decimal value 2019913825 is 0x78657041 in hexadecimal.
When converted to ASCII (little-endian), this spells: apex.

@JingMatrix JingMatrix linked an issue Jan 23, 2026 that may be closed by this pull request
1 task done
@JingMatrix

Copy link
Copy Markdown
Owner Author

@sekaiacg Please test again the latest CI build, and send me logs even if the problem is solved.

@JingMatrix JingMatrix linked an issue Jan 23, 2026 that may be closed by this pull request
1 task done
@sekaiacg

Copy link
Copy Markdown

@sekaiacg Please test again the latest CI build, and send me logs even if the problem is solved.

The problem is solved.
log: LSPosed_2026-01-23T11_36_52.755136.zip

@sekaiacg

sekaiacg commented Jan 23, 2026 •

Copy link
Copy Markdown

@JingMatrix

$ logcat | grep dex2oat                                                                           
01-23 14:21:20.749  2011  2011 V installd: Running /apex/com.android.art/bin/dex2oat64 in=base.apk out=/data/app/~~h1R84tIbCL74sMv4xcoztw==/com.bit747.clipboardfilter-HsN2LnTTMA7kLldQN7er6w==/oat/arm64/base.odex
01-23 14:21:20.758 14825 14825 D LSPosedDex2Oat: dex2oat.cpp:94#int main(int, char **): dex2oat wrapper ppid=2011
01-23 14:21:20.761 14825 14825 D LSPosedDex2Oat: dex2oat.cpp:123#int main(int, char **): sock: ia4edfivi4yoltlj7hv233sxxe28ifsx 6
01-23 14:21:20.761 14825 14825 D LSPosedDex2Oat: dex2oat.cpp:153#int main(int, char **): Executing via linker: /apex/com.android.runtime/bin/linker64 /proc/self/fd/6
01-23 14:21:20.833 14825 14825 I 6       : dex2oat took 55.206ms (48.430ms cpu) (threads: 6) arena alloc=0B (0B) java alloc=96KB (98512B) native alloc=2335KB (2391408B) free=504KB (516752B)
$ strings /data/app/~~h1R84tIbCL74sMv4xcoztw==/com.bit747.clipboardfilter-HsN2LnTTMA7kLldQN7er6w==/oat/arm64/base.odex
/proc/self/fd/6 --zip-fd=8 --zip-location=base.apk --oat-fd=9 --oat-location=/data/app/~~h1R84tIbCL74sMv4xcoztw==/com.bit747.clipboardfilter-HsN2LnTTMA7kLldQN7er6w==/oat/arm64/base.odex --input-vdex-fd=-1 --output-vdex-fd=10 --profile-file-fd=12 --swap-fd=11 --classpath-dir=/data/app/~~h1R84tIbCL74sMv4xcoztw==/com.bit747.clipboardfilter-HsN2LnTTMA7kLldQN7er6w== --class-loader-context=PCL[]{} --compact-dex-level=none --instruction-set=arm64 --instruction-set-features=default --instruction-set-variant=kryo300 --compiler-filter=speed-profile --compilation-reason=install --cpu-set=0,1,2,3,4,5,6,7 --max-image-block-size=524288 --resolve-startup-const-strings=true --generate-mini-debug-info --runtime-arg -Xtarget-sdk-version:30 --runtime-arg -Xhidden-api-policy:enabled -j6 --runtime-arg -Xms64m --runtime-arg -Xmx512m --inline-max-code-units=0

oathook is not working, it appears in the release version: --inline-max-code-units=0
This is suspicious: /proc/self/fd/6
log: LSPosed_2026-01-23T14_22_04.151792.zip

@JingMatrix

Copy link
Copy Markdown
Owner Author

Please upload your odex file for me to do more analysis.

@sekaiacg

Copy link
Copy Markdown

Please upload your odex file for me to do more analysis.

odex: base_odex.zip

We should also patch the cmdline path.

Hence, it is better to work through all the store.
@JingMatrix

Copy link
Copy Markdown
Owner Author

@sekaiacg Please test the latest CI build again.

@JingMatrix JingMatrix linked an issue Jan 23, 2026 that may be closed by this pull request
1 task done
@JingMatrix JingMatrix changed the title Use runtime apex linker to resolve library mismatches Refactor dex2oat wrapper to solve long-standing issues Jan 23, 2026
@sekaiacg

sekaiacg commented Jan 24, 2026 •

Copy link
Copy Markdown

@sekaiacg Please test the latest CI build again.

https://github.com/JingMatrix/LSPosed/actions/runs/21306967010

$ logcat | grep dex2oat
01-24 10:09:03.873  1977  1977 V installd: Running /apex/com.android.art/bin/dex2oat64 in=base.apk out=/data/app/~~ENtTjKqhrUzvCkVX-wO1BA==/com.bit747.clipboardfilter-b_N1x2xLB5AM7YXhSs6tZw==/oat/arm64/base.odex
01-24 10:09:04.008 16394 16394 I 4       : dex2oat took 84.640ms (66.958ms cpu) (threads: 6) arena alloc=0B (0B) java alloc=80KB (82128B) native alloc=2335KB (2391616B) free=476KB (487872B)

oathook is working properly.
odex:
base_odex.zip
log:
LSPosed_2026-01-24T10_10_25.948235.zip

@sekaiacg

sekaiacg commented Jan 24, 2026 •

Copy link
Copy Markdown

@JingMatrix

It will also crash if --inline-max-code-units=0 is not found.
Only the release version crashes.

01-24 19:50:55.193  2019 15188 V installd: Running /apex/com.android.art/bin/dex2oat64 in=base.apk out=/data/app/~~AM2g20tX-ao2uHPS9fEvVg==/com.bit747.clipboardfilter-Wy-lRvhM-89keDbDoh_0cw==/oat/arm64/base.odex
01-24 19:50:55.204 18554 18554 D LSPosedDex2Oat: dex2oat.cpp:108#int main(int, char **): dex2oat wrapper ppid=2019
01-24 19:50:55.205 18554 18554 D LSPosedDex2Oat: dex2oat.cpp:148#int main(int, char **): sock: u85prsbtvvben01i5inp1wxeh60tjy4x stock_fd: 6
01-24 19:50:55.205 18554 18554 D LSPosedDex2Oat: dex2oat.cpp:184#int main(int, char **): DEX2OAT_CMD set to /apex/com.android.art/bin/dex2oat64
01-24 19:50:55.213 18554 18554 V LSPosedDex2Oat: oat_hook.cpp:253#void initialize(): Found target: /apex/com.android.art/bin/dex2oat64 (dev: 64542, inode: 19)
01-24 19:50:55.272 18554 18554 I LSPosedDex2Oat: Parsed item:	[dex2oat-cmdline:/proc/self/fd/6 --zip-fd=8 --zip-location=base.apk --oat-fd=9 --oat-location=/data/app/~~AM2g20tX-ao2uHPS9fEvVg==/com.bit747.clipboardfilter-Wy-lRvhM-89keDbDoh_0cw==/oat/arm64/base.odex --input-vdex-fd=-1 --output-vdex-fd=10 --profile-file-fd=12 --swap-fd=11 --classpath-dir=/data/app/~~AM2g20tX-ao2uHPS9fEvVg==/com.bit747.clipboardfilter-Wy-lRvhM-89keDbDoh_0cw== --class-loader-context=PCL[]{} --compact-dex-level=none --instruction-set=arm64 --instruction-set-features=default --instruction-set-variant=kryo300 --compiler-filter=speed-profile --compilation-reason=install --cpu-set=0,1,2,3,4,5,6,7 --max-image-block-size=524288 --resolve-startup-const-strings=true --generate-mini-debug-info --runtime-arg -Xtarget-sdk-version:30 --runtime-arg -Xhidden-api-policy:enabled -j6 --runtime-arg -Xms64m --runtime-arg -Xmx512m --inline-max-code-units=0]
01-24 19:50:55.273 18554 18554 F libc    : Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x7b1a800000 in tid 18554 (dex2oat), pid 18554 (dex2oat)
01-24 19:50:55.301 18564 18564 F DEBUG   : pid: 18554, tid: 18554, name: dex2oat  >>> /apex/com.android.runtime/bin/linker64 <<<
01-24 19:50:55.301 18564 18564 F DEBUG   :       #02 pc 00000000000c75a4  /apex/com.android.art/bin/dex2oat64 (BuildId: 47a5d98386c930f4da87be488f7692c4e24b34eb)

test fork: https://github.com/sekaiacg/LSPosed/tree/dex2oat
ci: https://github.com/sekaiacg/LSPosed/actions/runs/21314361396
log: LSPosed_2026-01-24T19_53_17.914839.zip

The previous helper functions indeed overwrite the target functions in
the device binary, thus confuses the PLT hook.
@JingMatrix

JingMatrix commented Jan 24, 2026 •

Copy link
Copy Markdown
Owner Author

@sekaiacg Please test the latest CI build again.

Currently, the commit 97e2f55 is really mysterious, I still cannot figure out the actual cause.

@sekaiacg

Copy link
Copy Markdown

https://github.com/JingMatrix/LSPosed/actions/runs/21319656371

01-25 09:11:11.258  2039  2065 V installd: Running /apex/com.android.art/bin/dex2oat64 in=base.apk out=/data/app/~~otTD1khbjEvqbkuxuDTPLQ==/com.bit747.clipboardfilter-V9_xlukKxCZydrwWGISStA==/oat/arm64/base.odex
01-25 09:11:11.384 15377 15377 I 4       : dex2oat took 89.649ms (57.055ms cpu) (threads: 6) arena alloc=0B (0B) java alloc=80KB (82128B) native alloc=2196KB (2249440B) free=451KB (462112B)

/apex/com.android.art/bin/dex2oat64 --zip-fd=8 --zip-location=base.apk --oat-fd=9 --oat-location=/data/app/~~1F33Bx5H_5XktyosvNlIRw==/com.bit747.clipboardfilter-IsK4XVXH6HqgGP-yeYonDw==/oat/arm64/base.odex --input-vdex-fd=-1 --output-vdex-fd=10 --profile-file-fd=12 --swap-fd=11 --classpath-dir=/data/app/~~1F33Bx5H_5XktyosvNlIRw==/com.bit747.clipboardfilter-IsK4XVXH6HqgGP-yeYonDw== --class-loader-context=PCL[]{} --compact-dex-level=none --instruction-set=arm64 --instruction-set-features=default --instruction-set-variant=kryo300 --compiler-filter=speed-profile --compilation-reason=install --cpu-set=0,1,2,3,4,5,6,7 --max-image-block-size=524288 --resolve-startup-const-strings=true --generate-mini-debug-info --runtime-arg -Xtarget-sdk-version:30 --runtime-arg -Xhidden-api-policy:enabled -j6 --runtime-arg -Xms64m --runtime-arg -Xmx512m

working fine.
odex: base_odex.zip
log: LSPosed_2026-01-25T09_13_25.042572.zip


test fork: https://github.com/sekaiacg/LSPosed/commits/dex2oat
ci: https://github.com/sekaiacg/LSPosed/actions/runs/21324706063

01-25 09:38:59.502  2017  3190 V installd: Running /apex/com.android.art/bin/dex2oat64 in=base.apk out=/data/app/~~0H_KhsJGFA7NjeROOlLPqA==/com.bit747.clipboardfilter-oqIaZx2_64yPjtBD6LSCWw==/oat/arm64/base.odex
01-25 09:38:59.520 15432 15432 D LSPosedDex2Oat: dex2oat.cpp:108#int main(int, char **): dex2oat wrapper ppid=2017
01-25 09:38:59.522 15432 15432 D LSPosedDex2Oat: dex2oat.cpp:148#int main(int, char **): sock: 0jtdjcatl5mfn4xzw315oqg1hn4svb4z stock_fd: 6
01-25 09:38:59.522 15432 15432 D LSPosedDex2Oat: dex2oat.cpp:184#int main(int, char **): DEX2OAT_CMD set to /apex/com.android.art/bin/dex2oat64
01-25 09:38:59.550 15432 15432 V LSPosedDex2Oat: oat_hook.cpp:230#void initialize(): Found target: /apex/com.android.art/bin/dex2oat64 (dev: 64542, inode: 19)
01-25 09:38:59.711 15432 15432 I LSPosedDex2Oat: Parsed item:	[dex2oat-cmdline:/proc/self/fd/6 --zip-fd=8 --zip-location=base.apk --oat-fd=9 --oat-location=/data/app/~~0H_KhsJGFA7NjeROOlLPqA==/com.bit747.clipboardfilter-oqIaZx2_64yPjtBD6LSCWw==/oat/arm64/base.odex --input-vdex-fd=-1 --output-vdex-fd=10 --profile-file-fd=12 --swap-fd=11 --classpath-dir=/data/app/~~0H_KhsJGFA7NjeROOlLPqA==/com.bit747.clipboardfilter-oqIaZx2_64yPjtBD6LSCWw== --class-loader-context=PCL[]{} --compact-dex-level=none --instruction-set=arm64 --instruction-set-features=default --instruction-set-variant=kryo300 --compiler-filter=speed-profile --compilation-reason=install --cpu-set=0,1,2,3,4,5,6,7 --max-image-block-size=524288 --resolve-startup-const-strings=true --generate-mini-debug-info --runtime-arg -Xtarget-sdk-version:30 --runtime-arg -Xhidden-api-policy:enabled -j6 --runtime-arg -Xms64m --runtime-arg -Xmx512m --inline-max-code-units=0]
01-25 09:38:59.713 15432 15432 I 6       : dex2oat took 160.137ms (64.091ms cpu) (threads: 6) arena alloc=0B (0B) java alloc=96KB (98512B) native alloc=2337KB (2393552B) free=510KB (522800B)

/proc/self/fd/6 --zip-fd=8 --zip-location=base.apk --oat-fd=9 --oat-location=/data/app/~~0H_KhsJGFA7NjeROOlLPqA==/com.bit747.clipboardfilter-oqIaZx2_64yPjtBD6LSCWw==/oat/arm64/base.odex --input-vdex-fd=-1 --output-vdex-fd=10 --profile-file-fd=12 --swap-fd=11 --classpath-dir=/data/app/~~0H_KhsJGFA7NjeROOlLPqA==/com.bit747.clipboardfilter-oqIaZx2_64yPjtBD6LSCWw== --class-loader-context=PCL[]{} --compact-dex-level=none --instruction-set=arm64 --instruction-set-features=default --instruction-set-variant=kryo300 --compiler-filter=speed-profile --compilation-reason=install --cpu-set=0,1,2,3,4,5,6,7 --max-image-block-size=524288 --resolve-startup-const-strings=true --generate-mini-debug-info --runtime-arg -Xtarget-sdk-version:30 --runtime-arg -Xhidden-api-policy:enabled -j6 --runtime-arg -Xms64m --runtime-arg -Xmx512m --inline-max-code-units=0

It runs normally when --inline-max-code-units=0 is not found.
It seems that /proc/self/fd/6 is not being modified.
log: LSPosed_2026-01-25T09_44_28.201727.zip

@JingMatrix

Copy link
Copy Markdown
Owner Author

@sekaiacg Your test fork doesn't make any sense, no need to worry about it.

@JingMatrix
JingMatrix force-pushed the dex2oat branch 2 times, most recently from 4d2d056 to 9cb1938 Compare January 25, 2026 09:08
Manual library path injection via LD_LIBRARY_PATH has become unreliable due to symbol mismatches in core libraries (e.g., libc++) between the system and APEX partitions. Recent updates to `liblog` and `libbase` (in Android 16) have resulted in missing symbols like `__hash_memory` or `fmt` when the ART APEX binaries are forced to load system-partition shims.

This commit switches the wrapper to execute the runtime APEX linker directly (/apex/com.android.runtime/bin/linker64). By passing the dex2oat binary to the linker via `/proc/self/fd/`, the linker can properly initialize internal namespaces and resolve dependencies from the correct APEX and bootstrap locations.

Moreover, for the OatHeader hook, a bug introduced in 6703b45 is fixed, where the target functions of PLT hooks are overwritten by the our helper functions.

Details of the refactored project in explain in README.
@JingMatrix
JingMatrix merged commit 1436f69 into master Jan 25, 2026
@JingMatrix
JingMatrix deleted the dex2oat branch January 25, 2026 14:28
Enovale pushed a commit to Enovale/Vector that referenced this pull request Jul 13, 2026
Manual library path injection via LD_LIBRARY_PATH has become unreliable due to symbol mismatches in core libraries (e.g., `libc++`) between the system and APEX partitions. Recent updates to `liblog` and `libbase` (in Android 16) have resulted in missing symbols like `__hash_memory` or `fmt` when the ART APEX binaries are forced to load system-partition shims.

This commit switches the wrapper to execute the runtime APEX linker directly (e.g., `/apex/com.android.runtime/bin/linker64`). By passing the dex2oat binary to the linker via `/proc/self/fd/`, the linker can properly initialize internal namespaces and resolve dependencies from the correct APEX and bootstrap locations.

Moreover, for the OatHeader hook, a bug introduced in 256a4ab is now fixed, where the target functions of PLT hooks are overwritten by the our helper functions.

Details of the refactored project are explained in README.
rogerwwx pushed a commit to rogerwwx/LSPosed-Irena that referenced this pull request Sep 26, 2026
Manual LD_LIBRARY_PATH injection stopped working once APEX and system core
libraries (libc++/liblog/libbase) diverged on Android 16, breaking every
compilation while the wrapper was mounted. Execute the stock dex2oat binary
through /apex/com.android.runtime/bin/linker(64) instead, so the linker
resolves the compiler's libraries with its own namespace configuration, and
only fall back to the old fexecve path when that fails.

Ported from JingMatrix/Vector#515 (without its oat_header spoofing half,
which does not apply: this project disables inlining via the preload library
instead of a cmdline flag).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants