From eb0fa83691f74e1263462ea548c4c4eaffe1c9d0 Mon Sep 17 00:00:00 2001 From: mbricchi Date: Wed, 17 Jul 2024 22:02:30 +0200 Subject: [PATCH] android: Properly handle the CMC GC strategy - With Google Play System Updates the base version of libart may differ from the Android version. For example, an Android 12 system could be using libart equivalent to the system version on Android 14. - The function we were hooking in the MarkCompact GC was not the right spot to update the class pointers, causing crashes after some time. Fixes #323, for real this time. --- lib/android.js | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/lib/android.js b/lib/android.js index bdf1ace0..d696b89b 100644 --- a/lib/android.js +++ b/lib/android.js @@ -1808,6 +1808,9 @@ on_leave_gc_concurrent_copying_copying_phase (GumInvocationContext * ic) Gc: { copyingPhase: { onLeave: cm.on_leave_gc_concurrent_copying_copying_phase + }, + runFlip: { + onEnter: cm.on_leave_gc_concurrent_copying_copying_phase } } } @@ -1885,19 +1888,22 @@ function ensureArtKnowsHowToHandleReplacementMethods (vm) { const apiLevel = getAndroidApiLevel(); - let exportName = null; - if (apiLevel > 28) { - exportName = '_ZN3art2gc9collector17ConcurrentCopying12CopyingPhaseEv'; - } else if (apiLevel > 22) { - exportName = '_ZN3art2gc9collector17ConcurrentCopying12MarkingPhaseEv'; - } - - if (exportName !== null) { - Interceptor.attach(Module.getExportByName('libart.so', exportName), artController.hooks.Gc.copyingPhase); + const mayUseCollector = (apiLevel > 28) + ? new NativeFunction(Module.getExportByName('libart.so', '_ZNK3art2gc4Heap15MayUseCollectorENS0_13CollectorTypeE'), 'bool', ['pointer', 'int']) + : () => false; + const kCollectorTypeCMC = 3; - const collectorCMC = Module.findExportByName('libart.so', '_ZN3art2gc9collector11MarkCompact15CompactionPhaseEv'); - if (collectorCMC !== null) { - Interceptor.attach(collectorCMC, artController.hooks.Gc.copyingPhase); + if (mayUseCollector(getApi().artHeap, kCollectorTypeCMC)) { + Interceptor.attach(Module.getExportByName('libart.so', '_ZN3art6Thread15RunFlipFunctionEPS0_b'), artController.hooks.Gc.runFlip); + } else { + let exportName = null; + if (apiLevel > 28) { + exportName = '_ZN3art2gc9collector17ConcurrentCopying12CopyingPhaseEv'; + } else if (apiLevel > 22) { + exportName = '_ZN3art2gc9collector17ConcurrentCopying12MarkingPhaseEv'; + } + if (exportName !== null) { + Interceptor.attach(Module.getExportByName('libart.so', exportName), artController.hooks.Gc.copyingPhase); } } }