From 0110cf7e6e55821087b182d56c3e24bc5d7f6541 Mon Sep 17 00:00:00 2001 From: LoveSy Date: Thu, 6 Mar 2025 11:37:19 +0800 Subject: [PATCH] upgrade to ndk 29 an use module partition --- build.gradle.kts | 2 +- lsplant/src/main/jni/art/mirror/class.cxx | 14 +- .../src/main/jni/art/runtime/art_method.cxx | 12 +- .../src/main/jni/art/runtime/class_linker.cxx | 14 +- lsplant/src/main/jni/art/runtime/dex_file.cxx | 4 +- .../runtime/gc/scoped_gc_critical_section.cxx | 6 +- lsplant/src/main/jni/art/runtime/handle.cxx | 4 +- .../main/jni/art/runtime/instrumentation.cxx | 6 +- lsplant/src/main/jni/art/runtime/jit/jit.cxx | 8 +- .../jni/art/runtime/jit/jit_code_cache.cxx | 8 +- .../jni/art/runtime/jni/jni_id_manager.cxx | 8 +- lsplant/src/main/jni/art/runtime/runtime.cxx | 4 +- lsplant/src/main/jni/art/runtime/thread.cxx | 2 +- .../src/main/jni/art/runtime/thread_list.cxx | 2 +- lsplant/src/main/jni/common.cxx | 210 +++++++++--------- lsplant/src/main/jni/include/lsplant.ixx | 22 +- .../main/jni/include/utils/hook_helper.hpp | 54 ++--- lsplant/src/main/jni/lsplant.cc | 44 ++-- 18 files changed, 193 insertions(+), 231 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 74b81ff..64f17c0 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -6,5 +6,5 @@ val androidTargetSdkVersion by extra(35) val androidMinSdkVersion by extra(21) val androidBuildToolsVersion by extra("35.0.0") val androidCompileSdkVersion by extra(35) -val androidNdkVersion by extra("28.0.13004108") +val androidNdkVersion by extra("29.0.13113456") val androidCmakeVersion by extra("3.28.0+") diff --git a/lsplant/src/main/jni/art/mirror/class.cxx b/lsplant/src/main/jni/art/mirror/class.cxx index 75f1b18..d4f8981 100644 --- a/lsplant/src/main/jni/art/mirror/class.cxx +++ b/lsplant/src/main/jni/art/mirror/class.cxx @@ -4,17 +4,17 @@ module; #include "logging.hpp" -export module clazz; +export module lsplant:clazz; -import common; -import art_method; -import thread; -import handle; +import :common; +import :art_method; +import :thread; +import :handle; import hook_helper; -namespace lsplant::art::mirror { +export namespace lsplant::art::mirror { -export class Class { +class Class { private: inline static auto GetDescriptor_ = "_ZN3art6mirror5Class13GetDescriptorEPNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE"_sym.as; diff --git a/lsplant/src/main/jni/art/runtime/art_method.cxx b/lsplant/src/main/jni/art/runtime/art_method.cxx index 954558d..8b7efc9 100644 --- a/lsplant/src/main/jni/art/runtime/art_method.cxx +++ b/lsplant/src/main/jni/art/runtime/art_method.cxx @@ -6,17 +6,13 @@ module; #include "logging.hpp" -export module art_method; +export module lsplant:art_method; -import common; +import :common; import hook_helper; -namespace lsplant::art { -namespace mirror { -class Class; -} - -export class ArtMethod { +export namespace lsplant::art { +class ArtMethod { inline static auto PrettyMethod_ = "_ZN3art9ArtMethod12PrettyMethodEPS0_b"_sym.as; diff --git a/lsplant/src/main/jni/art/runtime/class_linker.cxx b/lsplant/src/main/jni/art/runtime/class_linker.cxx index 13a97d1..e97609c 100644 --- a/lsplant/src/main/jni/art/runtime/class_linker.cxx +++ b/lsplant/src/main/jni/art/runtime/class_linker.cxx @@ -4,15 +4,15 @@ module; #include "logging.hpp" -export module class_linker; +export module lsplant:class_linker; -import art_method; -import thread; -import common; -import clazz; -import handle; +import :art_method; +import :thread; +import :common; +import :clazz; +import :handle; +import :runtime; import hook_helper; -import runtime; namespace lsplant::art { export class ClassLinker { diff --git a/lsplant/src/main/jni/art/runtime/dex_file.cxx b/lsplant/src/main/jni/art/runtime/dex_file.cxx index fbbef40..219b8b7 100644 --- a/lsplant/src/main/jni/art/runtime/dex_file.cxx +++ b/lsplant/src/main/jni/art/runtime/dex_file.cxx @@ -6,9 +6,9 @@ module; #include "logging.hpp" -export module dex_file; +export module lsplant:dex_file; -import common; +import :common; import hook_helper; namespace lsplant::art { diff --git a/lsplant/src/main/jni/art/runtime/gc/scoped_gc_critical_section.cxx b/lsplant/src/main/jni/art/runtime/gc/scoped_gc_critical_section.cxx index 8b9a637..9880876 100644 --- a/lsplant/src/main/jni/art/runtime/gc/scoped_gc_critical_section.cxx +++ b/lsplant/src/main/jni/art/runtime/gc/scoped_gc_critical_section.cxx @@ -2,10 +2,10 @@ module; #include -export module scope_gc_critical_section; +export module lsplant:scope_gc_critical_section; -import thread; -import common; +import :thread; +import :common; import hook_helper; namespace lsplant::art::gc { diff --git a/lsplant/src/main/jni/art/runtime/handle.cxx b/lsplant/src/main/jni/art/runtime/handle.cxx index 8864e85..4d95616 100644 --- a/lsplant/src/main/jni/art/runtime/handle.cxx +++ b/lsplant/src/main/jni/art/runtime/handle.cxx @@ -3,9 +3,9 @@ module; #include #include -export module handle; +export module lsplant:handle; -import art_method; +import :art_method; namespace lsplant::art { diff --git a/lsplant/src/main/jni/art/runtime/instrumentation.cxx b/lsplant/src/main/jni/art/runtime/instrumentation.cxx index 4fdcc37..62d0051 100644 --- a/lsplant/src/main/jni/art/runtime/instrumentation.cxx +++ b/lsplant/src/main/jni/art/runtime/instrumentation.cxx @@ -2,10 +2,10 @@ module; #include "logging.hpp" -export module instrumentation; +export module lsplant:instrumentation; -import art_method; -import common; +import :art_method; +import :common; import hook_helper; namespace lsplant::art { diff --git a/lsplant/src/main/jni/art/runtime/jit/jit.cxx b/lsplant/src/main/jni/art/runtime/jit/jit.cxx index d2428b4..8f84696 100644 --- a/lsplant/src/main/jni/art/runtime/jit/jit.cxx +++ b/lsplant/src/main/jni/art/runtime/jit/jit.cxx @@ -2,11 +2,11 @@ module; #include "logging.hpp" -export module jit; +export module lsplant:jit; -import art_method; -import common; -import thread; +import :art_method; +import :common; +import :thread; import hook_helper; namespace lsplant::art::jit { diff --git a/lsplant/src/main/jni/art/runtime/jit/jit_code_cache.cxx b/lsplant/src/main/jni/art/runtime/jit/jit_code_cache.cxx index 76e51f4..2c825c7 100644 --- a/lsplant/src/main/jni/art/runtime/jit/jit_code_cache.cxx +++ b/lsplant/src/main/jni/art/runtime/jit/jit_code_cache.cxx @@ -2,11 +2,11 @@ module; #include "logging.hpp" -export module jit_code_cache; +export module lsplant:jit_code_cache; -import art_method; -import common; -import thread; +import :art_method; +import :common; +import :thread; import hook_helper; namespace lsplant::art::jit { diff --git a/lsplant/src/main/jni/art/runtime/jni/jni_id_manager.cxx b/lsplant/src/main/jni/art/runtime/jni/jni_id_manager.cxx index 07ca701..60f4984 100644 --- a/lsplant/src/main/jni/art/runtime/jni/jni_id_manager.cxx +++ b/lsplant/src/main/jni/art/runtime/jni/jni_id_manager.cxx @@ -2,11 +2,11 @@ module; #include "logging.hpp" -export module jni_id_manager; +export module lsplant:jni_id_manager; -import art_method; -import common; -import handle; +import :art_method; +import :common; +import :handle; import hook_helper; namespace lsplant::art::jni { diff --git a/lsplant/src/main/jni/art/runtime/runtime.cxx b/lsplant/src/main/jni/art/runtime/runtime.cxx index d36ec9e..f492fa0 100644 --- a/lsplant/src/main/jni/art/runtime/runtime.cxx +++ b/lsplant/src/main/jni/art/runtime/runtime.cxx @@ -5,9 +5,9 @@ module; #include "logging.hpp" -export module runtime; +export module lsplant:runtime; -import common; +import :common; import hook_helper; namespace lsplant::art { diff --git a/lsplant/src/main/jni/art/runtime/thread.cxx b/lsplant/src/main/jni/art/runtime/thread.cxx index b263225..812152c 100644 --- a/lsplant/src/main/jni/art/runtime/thread.cxx +++ b/lsplant/src/main/jni/art/runtime/thread.cxx @@ -1,6 +1,6 @@ module; -export module thread; +export module lsplant:thread; import hook_helper; diff --git a/lsplant/src/main/jni/art/runtime/thread_list.cxx b/lsplant/src/main/jni/art/runtime/thread_list.cxx index 4a62e13..64ff6f4 100644 --- a/lsplant/src/main/jni/art/runtime/thread_list.cxx +++ b/lsplant/src/main/jni/art/runtime/thread_list.cxx @@ -1,6 +1,6 @@ module; -export module thread_list; +export module lsplant:thread_list; import hook_helper; diff --git a/lsplant/src/main/jni/common.cxx b/lsplant/src/main/jni/common.cxx index 15766ba..8780f03 100644 --- a/lsplant/src/main/jni/common.cxx +++ b/lsplant/src/main/jni/common.cxx @@ -9,12 +9,12 @@ module; #include #include "logging.hpp" -#include "utils/jni_helper.hpp" -export module common; +export module lsplant:common; export import jni_helper; +export import hook_helper; -namespace lsplant { +export namespace lsplant { namespace art { class ArtMethod; @@ -22,12 +22,12 @@ namespace mirror { class Class; } namespace dex { -export class ClassDef {}; +class ClassDef {}; } // namespace dex } // namespace art -export enum class Arch { +enum class Arch { kArm, kArm64, kX86, @@ -61,119 +61,117 @@ template , size_t N = 4> using SharedHashSet = phmap::parallel_flat_hash_set; -export { - constexpr auto kArch = GetArch(); +constexpr auto kArch = GetArch(); - template - constexpr inline auto RoundUpTo(T v, size_t size) { - return v + size - 1 - ((v + size - 1) & (size - 1)); - } +template +constexpr inline auto RoundUpTo(T v, size_t size) { + return v + size - 1 - ((v + size - 1) & (size - 1)); +} - [[gnu::const]] inline auto GetAndroidApiLevel() { - static auto kApiLevel = []() { - std::array prop_value; - __system_property_get("ro.build.version.sdk", prop_value.data()); - int base = atoi(prop_value.data()); - __system_property_get("ro.build.version.preview_sdk", prop_value.data()); - return base + atoi(prop_value.data()); - }(); - return kApiLevel; - } +[[gnu::const]] inline auto GetAndroidApiLevel() { + static auto kApiLevel = []() { + std::array prop_value; + __system_property_get("ro.build.version.sdk", prop_value.data()); + int base = atoi(prop_value.data()); + __system_property_get("ro.build.version.preview_sdk", prop_value.data()); + return base + atoi(prop_value.data()); + }(); + return kApiLevel; +} - inline auto IsJavaDebuggable(JNIEnv * env) { - static auto kDebuggable = [&env]() { - auto sdk_int = GetAndroidApiLevel(); - if (sdk_int < __ANDROID_API_P__) { - return false; - } - auto runtime_class = JNI_FindClass(env, "dalvik/system/VMRuntime"); - if (!runtime_class) { - LOGE("Failed to find VMRuntime"); - return false; - } - auto get_runtime_method = JNI_GetStaticMethodID(env, runtime_class, "getRuntime", - "()Ldalvik/system/VMRuntime;"); - if (!get_runtime_method) { - LOGE("Failed to find VMRuntime.getRuntime()"); - return false; - } - auto is_debuggable_method = - JNI_GetMethodID(env, runtime_class, "isJavaDebuggable", "()Z"); - if (!is_debuggable_method) { - LOGE("Failed to find VMRuntime.isJavaDebuggable()"); - return false; - } - auto runtime = JNI_CallStaticObjectMethod(env, runtime_class, get_runtime_method); - if (!runtime) { - LOGE("Failed to get VMRuntime"); - return false; - } - bool is_debuggable = JNI_CallBooleanMethod(env, runtime, is_debuggable_method); - LOGD("java runtime debuggable %s", is_debuggable ? "true" : "false"); - return is_debuggable; - }(); - return kDebuggable; - } +inline auto IsJavaDebuggable(JNIEnv * env) { + static auto kDebuggable = [&env]() { + auto sdk_int = GetAndroidApiLevel(); + if (sdk_int < __ANDROID_API_P__) { + return false; + } + auto runtime_class = JNI_FindClass(env, "dalvik/system/VMRuntime"); + if (!runtime_class) { + LOGE("Failed to find VMRuntime"); + return false; + } + auto get_runtime_method = JNI_GetStaticMethodID(env, runtime_class, "getRuntime", + "()Ldalvik/system/VMRuntime;"); + if (!get_runtime_method) { + LOGE("Failed to find VMRuntime.getRuntime()"); + return false; + } + auto is_debuggable_method = + JNI_GetMethodID(env, runtime_class, "isJavaDebuggable", "()Z"); + if (!is_debuggable_method) { + LOGE("Failed to find VMRuntime.isJavaDebuggable()"); + return false; + } + auto runtime = JNI_CallStaticObjectMethod(env, runtime_class, get_runtime_method); + if (!runtime) { + LOGE("Failed to get VMRuntime"); + return false; + } + bool is_debuggable = JNI_CallBooleanMethod(env, runtime, is_debuggable_method); + LOGD("java runtime debuggable %s", is_debuggable ? "true" : "false"); + return is_debuggable; + }(); + return kDebuggable; +} - constexpr auto kPointerSize = sizeof(void *); +constexpr auto kPointerSize = sizeof(void *); - SharedHashMap> hooked_methods_; +SharedHashMap> hooked_methods_; - SharedHashMap> - hooked_classes_; +SharedHashMap> + hooked_classes_; - SharedHashSet deoptimized_methods_set_; +SharedHashSet deoptimized_methods_set_; - SharedHashMap> - deoptimized_classes_; +SharedHashMap> + deoptimized_classes_; - std::list> jit_movements_; - std::shared_mutex jit_movements_lock_; +std::list> jit_movements_; +std::shared_mutex jit_movements_lock_; - inline art::ArtMethod *IsHooked(art::ArtMethod * art_method, bool including_backup = false) { - art::ArtMethod *backup = nullptr; - hooked_methods_.if_contains(art_method, [&backup, &including_backup](const auto &it) { - if (including_backup || it.second.first) backup = it.second.second; +inline art::ArtMethod *IsHooked(art::ArtMethod * art_method, bool including_backup = false) { + art::ArtMethod *backup = nullptr; + hooked_methods_.if_contains(art_method, [&backup, &including_backup](const auto &it) { + if (including_backup || it.second.first) backup = it.second.second; + }); + return backup; +} + +inline art::ArtMethod *IsBackup(art::ArtMethod * art_method) { + art::ArtMethod *backup = nullptr; + hooked_methods_.if_contains(art_method, [&backup](const auto &it) { + if (!it.second.first) backup = it.second.second; + }); + return backup; +} + +inline bool IsDeoptimized(art::ArtMethod * art_method) { + return deoptimized_methods_set_.contains(art_method); +} + +inline std::list> GetJitMovements() { + std::unique_lock lk(jit_movements_lock_); + return std::move(jit_movements_); +} + +inline void RecordHooked(art::ArtMethod * target, const art::dex::ClassDef *class_def, + jobject reflected_backup, art::ArtMethod *backup) { + hooked_classes_.lazy_emplace_l( + class_def, [&target](auto &it) { it.second.emplace(target); }, + [&class_def, &target](const auto &ctor) { + ctor(class_def, phmap::flat_hash_set{target}); }); - return backup; - } + hooked_methods_.insert({std::make_pair(target, std::make_pair(reflected_backup, backup)), + std::make_pair(backup, std::make_pair(nullptr, target))}); +} - inline art::ArtMethod *IsBackup(art::ArtMethod * art_method) { - art::ArtMethod *backup = nullptr; - hooked_methods_.if_contains(art_method, [&backup](const auto &it) { - if (!it.second.first) backup = it.second.second; - }); - return backup; - } +inline void RecordDeoptimized(const art::dex::ClassDef *class_def, art::ArtMethod *art_method) { + { deoptimized_classes_[class_def].emplace(art_method); } + deoptimized_methods_set_.insert(art_method); +} - inline bool IsDeoptimized(art::ArtMethod * art_method) { - return deoptimized_methods_set_.contains(art_method); - } - - inline std::list> GetJitMovements() { - std::unique_lock lk(jit_movements_lock_); - return std::move(jit_movements_); - } - - inline void RecordHooked(art::ArtMethod * target, const art::dex::ClassDef *class_def, - jobject reflected_backup, art::ArtMethod *backup) { - hooked_classes_.lazy_emplace_l( - class_def, [&target](auto &it) { it.second.emplace(target); }, - [&class_def, &target](const auto &ctor) { - ctor(class_def, phmap::flat_hash_set{target}); - }); - hooked_methods_.insert({std::make_pair(target, std::make_pair(reflected_backup, backup)), - std::make_pair(backup, std::make_pair(nullptr, target))}); - } - - inline void RecordDeoptimized(const art::dex::ClassDef *class_def, art::ArtMethod *art_method) { - { deoptimized_classes_[class_def].emplace(art_method); } - deoptimized_methods_set_.insert(art_method); - } - - inline void RecordJitMovement(art::ArtMethod * target, art::ArtMethod * backup) { - std::unique_lock lk(jit_movements_lock_); - jit_movements_.emplace_back(target, backup); - } +inline void RecordJitMovement(art::ArtMethod * target, art::ArtMethod * backup) { + std::unique_lock lk(jit_movements_lock_); + jit_movements_.emplace_back(target, backup); } } // namespace lsplant diff --git a/lsplant/src/main/jni/include/lsplant.ixx b/lsplant/src/main/jni/include/lsplant.ixx index fb4bead..d7c19ec 100644 --- a/lsplant/src/main/jni/include/lsplant.ixx +++ b/lsplant/src/main/jni/include/lsplant.ixx @@ -4,16 +4,14 @@ module; export module lsplant; -export namespace lsplant { - inline namespace v2 { - using lsplant::v2::InitInfo; - using lsplant::v2::Init; - using lsplant::v2::Hook; - using lsplant::v2::UnHook; - using lsplant::v2::IsHooked; - using lsplant::v2::Deoptimize; - using lsplant::v2::GetNativeFunction; - using lsplant::v2::MakeClassInheritable; - using lsplant::v2::MakeDexFileTrusted; - } +export namespace lsplant::inline v2{ + using lsplant::v2::InitInfo; + using lsplant::v2::Init; + using lsplant::v2::Hook; + using lsplant::v2::UnHook; + using lsplant::v2::IsHooked; + using lsplant::v2::Deoptimize; + using lsplant::v2::GetNativeFunction; + using lsplant::v2::MakeClassInheritable; + using lsplant::v2::MakeDexFileTrusted; } diff --git a/lsplant/src/main/jni/include/utils/hook_helper.hpp b/lsplant/src/main/jni/include/utils/hook_helper.hpp index d1b5f1f..a1502d2 100644 --- a/lsplant/src/main/jni/include/utils/hook_helper.hpp +++ b/lsplant/src/main/jni/include/utils/hook_helper.hpp @@ -12,13 +12,6 @@ namespace lsplant { template struct FixedString { consteval FixedString(const char (&str)[N]) { std::copy_n(str, N, data); } -#if defined(__LP64__) - template - consteval FixedString(const char (&)[M], const char (&str)[N]) : FixedString(str) {} -#else - template - consteval FixedString(const char (&str)[N], const char (&)[M]) : FixedString(str) {} -#endif char data[N] = {}; }; @@ -181,29 +174,11 @@ private: } }; - -struct Dummy; +template +concept Backup = std::is_function_v>; template -concept Backup = std::is_function_v> || requires(F&& f) { { f(std::declval()) } -> std::same_as; }; - -template -concept MemBackup = std::is_function_v> || requires(F&& f) { { f(std::declval()) } -> std::same_as; }; - -template -T return_t(); - -// for ndk 29+, use decltype(F::template operator()<&decltype([] static {})::operator()>) -// and remove Dummy, set MemBackup as std::is_member_function_pointer_v -template -using Signature = decltype(F::template operator()<[](auto...a) static { - using D = std::conditional_t; - if constexpr ((false || ... || std::is_same_v)) { - return return_t(); - } else { - return return_t D {}>(std::declval()...))>(); - } -}>); +concept MemBackup = std::is_member_function_pointer_v> || Backup; template struct Symbol { @@ -218,21 +193,18 @@ struct Symbol { [[no_unique_address]] struct Hook { template - requires(requires { std::declval>(); }) auto operator->*(F&&) const { - using HookerType = Hooker>; - return HookerType{static_cast(&F::template operator())}; + using Signature = decltype(F::template operator()<&decltype([] static {})::operator()>); + if constexpr (requires { F::template operator()<&decltype([] {})::operator()>; }) { + using HookerType = Hooker(Ret(*)(This*, Args...)) -> Ret(This::*)(Args...) { + return {}; + }.template operator()(std::declval()))>; + return HookerType{static_cast(&F::template operator())}; + } else { + using HookerType = Hooker; + return HookerType{static_cast(&F::template operator())}; + } }; - template - requires(requires { std::declval>(); }) - auto operator->*(F&&) const { - constexpr auto c = [](Ret(*f)(This*, Args...)) -> Ret(This::*)(Args...) { - return {}; - }; - using HookerType = Hooker>()))>; - return HookerType{static_cast(&F::template operator())}; - }; - } hook; }; diff --git a/lsplant/src/main/jni/lsplant.cc b/lsplant/src/main/jni/lsplant.cc index 90db37e..fa5222e 100644 --- a/lsplant/src/main/jni/lsplant.cc +++ b/lsplant/src/main/jni/lsplant.cc @@ -1,3 +1,7 @@ +module; + +#include "lsplant.hpp" + #include #include #include @@ -12,29 +16,23 @@ #include "logging.hpp" +module lsplant; + import dex_builder; -import lsplant; -import common; -import art_method; -import clazz; -import thread; -import instrumentation; -import runtime; -import thread_list; -import class_linker; -import scope_gc_critical_section; -import jit_code_cache; -import jni_id_manager; -import dex_file; -import jit; -import hook_helper; - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunknown-pragmas" -#pragma ide diagnostic ignored "ConstantConditionsOC" -#pragma ide diagnostic ignored "Simplify" -#pragma ide diagnostic ignored "UnreachableCode" +import :common; +import :art_method; +import :clazz; +import :thread; +import :instrumentation; +import :runtime; +import :thread_list; +import :class_linker; +import :scope_gc_critical_section; +import :jit_code_cache; +import :jni_id_manager; +import :dex_file; +import :jit; namespace lsplant { @@ -633,6 +631,7 @@ std::string GetProxyMethodShorty(JNIEnv *env, jobject proxy_method) { } // namespace inline namespace v2 { +extern "C++" { using ::lsplant::IsHooked; @@ -835,8 +834,7 @@ using ::lsplant::IsHooked; if (!cookie) return false; return DexFile::SetTrusted(env, cookie); } +} } // namespace v2 } // namespace lsplant - -#pragma clang diagnostic pop