diff --git a/build.gradle.kts b/build.gradle.kts index afc9f6a..74b81ff 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("27.0.12077973") +val androidNdkVersion by extra("28.0.13004108") 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 86ea836..bcc0066 100644 --- a/lsplant/src/main/jni/art/mirror/class.cxx +++ b/lsplant/src/main/jni/art/mirror/class.cxx @@ -16,14 +16,11 @@ namespace lsplant::art::mirror { export class Class { private: - inline static MemberFunction< - "_ZN3art6mirror5Class13GetDescriptorEPNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE", - Class, const char *(std::string *)> - GetDescriptor_; + inline static auto GetDescriptor_ = + "_ZN3art6mirror5Class13GetDescriptorEPNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE"_sym.as; - inline static MemberFunction<"_ZN3art6mirror5Class11GetClassDefEv", Class, - const dex::ClassDef *()> - GetClassDef_; + inline static auto GetClassDef_ = + "_ZN3art6mirror5Class11GetClassDefEv"_sym.as; using BackupMethods = phmap::flat_hash_map; inline static phmap::flat_hash_map, uint8_t, Thread *)> - SetClassStatus_ = +[](TrivialHandle h, uint8_t new_status, Thread *self) { + inline static auto SetClassStatus_ = + "_ZN3art6mirror5Class9SetStatusENS_6HandleIS1_EENS_11ClassStatusEPNS_6ThreadE"_sym.hook->*[] + + (TrivialHandle h, uint8_t new_status, Thread *self) static -> void { if (new_status == initialized_status) { BackupClassMethods(GetClassDef_(h.Get()), self); } - return SetClassStatus_(h, new_status, self); + return backup(h, new_status, self); }; - inline static Hooker<"_ZN3art6mirror5Class9SetStatusENS_6HandleIS1_EENS1_6StatusEPNS_6ThreadE", - void(Handle, int, Thread *)> - SetStatus_ = +[](Handle h, int new_status, Thread *self) { + inline static auto SetStatus_ = + "_ZN3art6mirror5Class9SetStatusENS_6HandleIS1_EENS1_6StatusEPNS_6ThreadE"_sym.hook->*[] + + (Handle h, int new_status, Thread *self) static -> void { if (new_status == static_cast(initialized_status)) { BackupClassMethods(GetClassDef_(h.Get()), self); } - return SetStatus_(h, new_status, self); + return backup(h, new_status, self); }; - inline static Hooker<"_ZN3art6mirror5Class9SetStatusENS_6HandleIS1_EENS1_6StatusEPNS_6ThreadE", - void(TrivialHandle, uint32_t, Thread *)> - TrivialSetStatus_ = +[](TrivialHandle h, uint32_t new_status, Thread *self) { + inline static auto TrivialSetStatus_ = + "_ZN3art6mirror5Class9SetStatusENS_6HandleIS1_EENS1_6StatusEPNS_6ThreadE"_sym.hook->*[] + + (TrivialHandle h, uint32_t new_status, Thread *self) static -> void { if (new_status == initialized_status) { BackupClassMethods(GetClassDef_(h.Get()), self); } - return TrivialSetStatus_(h, new_status, self); + return backup(h, new_status, self); }; - inline static Hooker<"_ZN3art6mirror5Class9SetStatusENS1_6StatusEPNS_6ThreadE", - void(Class *, int, Thread *)> - ClassSetStatus_ = +[](Class *thiz, int new_status, Thread *self) { + inline static auto ClassSetStatus_ = + "_ZN3art6mirror5Class9SetStatusENS1_6StatusEPNS_6ThreadE"_sym.hook->*[] + + (Class *thiz, int new_status, Thread *self) static -> void { if (new_status == static_cast(initialized_status)) { BackupClassMethods(GetClassDef_(thiz), self); } - return ClassSetStatus_(thiz, new_status, self); + return backup(thiz, new_status, self); }; public: diff --git a/lsplant/src/main/jni/art/runtime/art_method.cxx b/lsplant/src/main/jni/art/runtime/art_method.cxx index 854a02e..2c43cdd 100644 --- a/lsplant/src/main/jni/art/runtime/art_method.cxx +++ b/lsplant/src/main/jni/art/runtime/art_method.cxx @@ -17,30 +17,26 @@ class Class; } export class ArtMethod { - inline static MemberFunction<"_ZN3art9ArtMethod12PrettyMethodEPS0_b", ArtMethod, - std::string(bool)> - PrettyMethod_; + inline static auto PrettyMethod_ = + "_ZN3art9ArtMethod12PrettyMethodEPS0_b"_sym.as; - inline static Function<"_ZN3art12PrettyMethodEPNS_9ArtMethodEb", - std::string(ArtMethod *thiz, bool with_signature)> - PrettyMethodStatic_; + inline static auto PrettyMethodStatic_ = + "_ZN3art12PrettyMethodEPNS_9ArtMethodEb"_sym.as; - inline static Function<"_ZN3art12PrettyMethodEPNS_6mirror9ArtMethodEb", - std::string(ArtMethod *thiz, bool with_signature)> - PrettyMethodMirror_; + inline static auto PrettyMethodMirror_ = + "_ZN3art12PrettyMethodEPNS_6mirror9ArtMethodEb"_sym.as; - inline static Function<"_ZN3artL15GetMethodShortyEP7_JNIEnvP10_jmethodID", - const char *(JNIEnv *env, jmethodID method)> - GetMethodShortyL_; - inline static Function<"_ZN3art15GetMethodShortyEP7_JNIEnvP10_jmethodID", - const char *(JNIEnv *env, jmethodID mid)> - GetMethodShorty_; + inline static auto GetMethodShortyL_ = + "_ZN3artL15GetMethodShortyEP7_JNIEnvP10_jmethodID"_sym.as; - inline static MemberFunction<"_ZN3art9ArtMethod24ThrowInvocationTimeErrorEv", ArtMethod, void()> - ThrowInvocationTimeError_; + inline static auto GetMethodShorty_ = + "_ZN3art15GetMethodShortyEP7_JNIEnvP10_jmethodID"_sym.as; - inline static Function<"artInterpreterToCompiledCodeBridge", void()> - art_interpreter_to_compiled_code_bridge_; + inline static auto ThrowInvocationTimeError_ = + "_ZN3art9ArtMethod24ThrowInvocationTimeErrorEv"_sym.as; + + inline static auto art_interpreter_to_compiled_code_bridge_ = + "artInterpreterToCompiledCodeBridge"_sym.as; inline void ThrowInvocationTimeError() { if (ThrowInvocationTimeError_) { diff --git a/lsplant/src/main/jni/art/runtime/class_linker.cxx b/lsplant/src/main/jni/art/runtime/class_linker.cxx index 1720194..489bf41 100644 --- a/lsplant/src/main/jni/art/runtime/class_linker.cxx +++ b/lsplant/src/main/jni/art/runtime/class_linker.cxx @@ -17,28 +17,27 @@ import runtime; namespace lsplant::art { export class ClassLinker { private: - inline static MemberFunction< - "_ZNK3art11ClassLinker27SetEntryPointsToInterpreterEPNS_9ArtMethodE", ClassLinker, - void(ArtMethod *)> - SetEntryPointsToInterpreter_; + inline static auto SetEntryPointsToInterpreter_ = + "_ZNK3art11ClassLinker27SetEntryPointsToInterpreterEPNS_9ArtMethodE"_sym.as; - inline static Hooker<"_ZN3art11ClassLinker30ShouldUseInterpreterEntrypointEPNS_9ArtMethodEPKv", - bool(ArtMethod *, const void *)> - ShouldUseInterpreterEntrypoint_ = +[](ArtMethod *art_method, const void *quick_code) { + inline static auto ShouldUseInterpreterEntrypoint_ = + "_ZN3art11ClassLinker30ShouldUseInterpreterEntrypointEPNS_9ArtMethodEPKv"_sym.hook->*[] + + (ArtMethod *art_method, const void *quick_code)static -> bool { if (quick_code != nullptr && IsHooked(art_method)) [[unlikely]] { return false; } - return ShouldUseInterpreterEntrypoint_(art_method, quick_code); + return backup(art_method, quick_code); }; - inline static Function<"art_quick_to_interpreter_bridge", void(void *)> - art_quick_to_interpreter_bridge_; + inline static auto art_quick_to_interpreter_bridge_ = + "art_quick_to_interpreter_bridge"_sym.as; - inline static Function<"_ZN3art15instrumentationL19GetOptimizedCodeForEPNS_9ArtMethodE", - void *(ArtMethod *)> GetOptimizedCodeFor_; + inline static auto GetOptimizedCodeFor_ = + "_ZN3art15instrumentationL19GetOptimizedCodeForEPNS_9ArtMethodE"_sym.as; - inline static MemberFunction<"_ZNK3art11ClassLinker29GetRuntimeQuickGenericJniStubEv", - ClassLinker, void *()> GetRuntimeQuickGenericJniStub_; + inline static auto GetRuntimeQuickGenericJniStub_= + "_ZNK3art11ClassLinker29GetRuntimeQuickGenericJniStubEv"_sym.as; inline static art::ArtMethod *MayGetBackup(art::ArtMethod *method) { if (auto backup = IsHooked(method); backup) [[unlikely]] { @@ -48,57 +47,60 @@ private: return method; } - inline static MemberHooker<"_ZN3art6mirror9ArtMethod14RegisterNativeEPNS_6ThreadEPKvb", - ClassLinker, void(ArtMethod *, Thread *, const void *, bool)> - RegisterNativeThread_ = +[](ClassLinker *thiz, ArtMethod *method, Thread *thread, - const void *native_method, bool is_fast) { - return RegisterNativeThread_(thiz, MayGetBackup(method), thread, native_method, - is_fast); + inline static auto RegisterNativeThread_ = + "_ZN3art6mirror9ArtMethod14RegisterNativeEPNS_6ThreadEPKvb"_sym.hook->*[] + + (ClassLinker *thiz, ArtMethod *method, Thread *thread, const void *native_method, bool is_fast) static -> void { + return backup(thiz, MayGetBackup(method), thread, native_method, is_fast); }; - inline static MemberHooker<"_ZN3art6mirror9ArtMethod16UnregisterNativeEPNS_6ThreadE", - ClassLinker, void(ArtMethod *, Thread *)> - UnregisterNativeThread_ = +[](ClassLinker *thiz, ArtMethod *method, Thread *thread) { - return UnregisterNativeThread_(thiz, MayGetBackup(method), thread); + inline static auto UnregisterNativeThread_ = + "_ZN3art6mirror9ArtMethod16UnregisterNativeEPNS_6ThreadE"_sym.hook->*[] + + (ClassLinker *thiz, ArtMethod *method, Thread *thread) static -> void { + return backup(thiz, MayGetBackup(method), thread); }; - inline static MemberHooker<"_ZN3art9ArtMethod14RegisterNativeEPKvb", ClassLinker, - void(ArtMethod *, const void *, bool)> - RegisterNativeFast_ = - +[](ClassLinker *thiz, ArtMethod *method, const void *native_method, bool is_fast) { - return RegisterNativeFast_(thiz, MayGetBackup(method), native_method, is_fast); - }; - - inline static MemberHooker<"_ZN3art9ArtMethod16UnregisterNativeEv", ClassLinker, - void(ArtMethod *)> - UnregisterNativeFast_ = +[](ClassLinker *thiz, ArtMethod *method) { - return UnregisterNativeFast_(thiz, MayGetBackup(method)); + inline static auto RegisterNativeFast_ = + "_ZN3art9ArtMethod14RegisterNativeEPKvb"_sym.hook->*[] + + (ClassLinker *thiz, ArtMethod *method, const void *native_method, bool is_fast) static -> void { + return backup(thiz, MayGetBackup(method), native_method, is_fast); }; - inline static MemberHooker<"_ZN3art9ArtMethod14RegisterNativeEPKv", ClassLinker, - const void *(ArtMethod *, const void *)> - RegisterNative_ = +[](ClassLinker *thiz, ArtMethod *method, const void *native_method) { - return RegisterNative_(thiz, MayGetBackup(method), native_method); + inline static auto UnregisterNativeFast_ = + "_ZN3art9ArtMethod16UnregisterNativeEv"_sym.hook->*[] + + (ClassLinker *thiz, ArtMethod *method) static -> void{ + return backup(thiz, MayGetBackup(method)); }; - inline static MemberHooker<"_ZN3art9ArtMethod16UnregisterNativeEv", ClassLinker, - const void *(ArtMethod *)> - UnregisterNative_ = +[](ClassLinker *thiz, ArtMethod *method) { - return UnregisterNative_(thiz, MayGetBackup(method)); + inline static auto RegisterNative_ = + "_ZN3art9ArtMethod14RegisterNativeEPKv"_sym.hook->*[] + + (ClassLinker *thiz, ArtMethod *method, const void *native_method) static -> const void * { + return backup(thiz, MayGetBackup(method), native_method); }; - inline static MemberHooker< - "_ZN3art11ClassLinker14RegisterNativeEPNS_6ThreadEPNS_9ArtMethodEPKv", ClassLinker, - const void *(Thread *, ArtMethod *, const void *)> - RegisterNativeClassLinker_ = - +[](ClassLinker *thiz, Thread *self, ArtMethod *method, const void *native_method) { - return RegisterNativeClassLinker_(thiz, self, MayGetBackup(method), native_method); - }; + inline static auto UnregisterNative_ = + "_ZN3art9ArtMethod16UnregisterNativeEv"_sym.hook->*[] + + (ClassLinker *thiz, ArtMethod *method) static -> const void * { + return backup(thiz, MayGetBackup(method)); + }; - inline static MemberHooker<"_ZN3art11ClassLinker16UnregisterNativeEPNS_6ThreadEPNS_9ArtMethodE", - ClassLinker, const void *(Thread *, ArtMethod *)> - UnregisterNativeClassLinker_ = +[](ClassLinker *thiz, Thread *self, ArtMethod *method) { - return UnregisterNativeClassLinker_(thiz, self, MayGetBackup(method)); + inline static auto RegisterNativeClassLinker_ = + "_ZN3art11ClassLinker14RegisterNativeEPNS_6ThreadEPNS_9ArtMethodEPKv"_sym.hook->*[] + + (ClassLinker *thiz, Thread *self, ArtMethod *method, const void *native_method) static -> const void *{ + return backup(thiz, self, MayGetBackup(method), native_method); + }; + + inline static auto UnregisterNativeClassLinker_ = + "_ZN3art11ClassLinker16UnregisterNativeEPNS_6ThreadEPNS_9ArtMethodE"_sym.hook->*[] + + (ClassLinker *thiz, Thread *self, ArtMethod *method) static -> const void * { + return backup(thiz, self, MayGetBackup(method)); }; static void RestoreBackup(const dex::ClassDef *class_def, art::Thread *self) { @@ -123,44 +125,44 @@ private: } } - inline static MemberHooker< - "_ZN3art11ClassLinker22FixupStaticTrampolinesENS_6ObjPtrINS_6mirror5ClassEEE", ClassLinker, - void(ObjPtr)> - FixupStaticTrampolines_ = +[](ClassLinker *thiz, ObjPtr mirror_class) { - FixupStaticTrampolines_(thiz, mirror_class); + inline static auto FixupStaticTrampolines_ = + "_ZN3art11ClassLinker22FixupStaticTrampolinesENS_6ObjPtrINS_6mirror5ClassEEE"_sym.hook->*[] + + (ClassLinker *thiz, ObjPtr mirror_class) static -> void { + backup(thiz, mirror_class); RestoreBackup(mirror_class->GetClassDef(), nullptr); }; - inline static MemberHooker< - "_ZN3art11ClassLinker22FixupStaticTrampolinesEPNS_6ThreadENS_6ObjPtrINS_6mirror5ClassEEE", - ClassLinker, void(Thread *, ObjPtr)> - FixupStaticTrampolinesWithThread_ = - +[](ClassLinker *thiz, Thread *self, ObjPtr mirror_class) { - FixupStaticTrampolinesWithThread_(thiz, self, mirror_class); - RestoreBackup(mirror_class->GetClassDef(), self); - }; + inline static auto FixupStaticTrampolinesWithThread_ = + "_ZN3art11ClassLinker22FixupStaticTrampolinesEPNS_6ThreadENS_6ObjPtrINS_6mirror5ClassEEE"_sym.hook->*[] + + (ClassLinker *thiz, Thread *self, ObjPtr mirror_class) static -> void { + backup(thiz, self, mirror_class); + RestoreBackup(mirror_class->GetClassDef(), self); + }; - inline static MemberHooker<"_ZN3art11ClassLinker22FixupStaticTrampolinesEPNS_6mirror5ClassE", - ClassLinker, void(mirror::Class *)> - FixupStaticTrampolinesRaw_ = +[](ClassLinker *thiz, mirror::Class *mirror_class) { - FixupStaticTrampolinesRaw_(thiz, mirror_class); + inline static auto FixupStaticTrampolinesRaw_ = + "_ZN3art11ClassLinker22FixupStaticTrampolinesEPNS_6mirror5ClassE"_sym.hook->*[] + + (ClassLinker *thiz, mirror::Class *mirror_class)static -> void { + backup(thiz, mirror_class); RestoreBackup(mirror_class->GetClassDef(), nullptr); }; - inline static MemberHooker< - {"_ZN3art11ClassLinker26VisiblyInitializedCallback29AdjustThreadVisibilityCounterEPNS_6ThreadEi", - "_ZN3art11ClassLinker26VisiblyInitializedCallback29AdjustThreadVisibilityCounterEPNS_6ThreadEl"}, - ClassLinker, void(Thread *, ssize_t)> - AdjustThreadVisibilityCounter_ = +[](ClassLinker *thiz, Thread *self, ssize_t adjustment) { - AdjustThreadVisibilityCounter_(thiz, self, adjustment); + inline static auto AdjustThreadVisibilityCounter_ = + ("_ZN3art11ClassLinker26VisiblyInitializedCallback29AdjustThreadVisibilityCounterEPNS_6ThreadEi"_sym | + "_ZN3art11ClassLinker26VisiblyInitializedCallback29AdjustThreadVisibilityCounterEPNS_6ThreadEl"_sym).hook->*[] + + (ClassLinker *thiz, Thread *self, ssize_t adjustment) static -> void { + backup(thiz, self, adjustment); RestoreBackup(nullptr, self); }; - inline static MemberHooker< - "_ZN3art11ClassLinker26VisiblyInitializedCallback22MarkVisiblyInitializedEPNS_6ThreadE", - ClassLinker, void(Thread *)> - MarkVisiblyInitialized_ = +[](ClassLinker *thiz, Thread *self) { - MarkVisiblyInitialized_(thiz, self); + inline static auto MarkVisiblyInitialized_ = + "_ZN3art11ClassLinker26VisiblyInitializedCallback22MarkVisiblyInitializedEPNS_6ThreadE"_sym.hook->*[] + + (ClassLinker *thiz, Thread *self) static -> void { + backup(thiz, self); RestoreBackup(nullptr, self); }; diff --git a/lsplant/src/main/jni/art/runtime/dex_file.cxx b/lsplant/src/main/jni/art/runtime/dex_file.cxx index 031f996..e9e4dca 100644 --- a/lsplant/src/main/jni/art/runtime/dex_file.cxx +++ b/lsplant/src/main/jni/art/runtime/dex_file.cxx @@ -18,32 +18,28 @@ export class DexFile { uint32_t checksum_; // See also location_checksum_ }; - inline static Function< - {"_ZN3art7DexFile10OpenMemoryEPKhjRKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEjPNS_6MemMapEPKNS_10OatDexFileEPS9_", - "_ZN3art7DexFile10OpenMemoryEPKhmRKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEjPNS_6MemMapEPKNS_10OatDexFileEPS9_"}, + inline static auto OpenMemory_ = + ("_ZN3art7DexFile10OpenMemoryEPKhjRKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEjPNS_6MemMapEPKNS_10OatDexFileEPS9_"_sym | + "_ZN3art7DexFile10OpenMemoryEPKhmRKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEjPNS_6MemMapEPKNS_10OatDexFileEPS9_"_sym).as< std::unique_ptr(const uint8_t* dex_file, size_t size, const std::string& location, uint32_t location_checksum, void* mem_map, - const void* oat_dex_file, std::string* error_msg)> - OpenMemory_; + const void* oat_dex_file, std::string* error_msg)>; - inline static Function< - {"_ZN3art7DexFile10OpenMemoryEPKhjRKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEjPNS_6MemMapEPKNS_7OatFileEPS9_", - "_ZN3art7DexFile10OpenMemoryEPKhmRKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEjPNS_6MemMapEPKNS_7OatFileEPS9_"}, + inline static auto OpenMemoryRaw_ = + ("_ZN3art7DexFile10OpenMemoryEPKhjRKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEjPNS_6MemMapEPKNS_7OatFileEPS9_"_sym | + "_ZN3art7DexFile10OpenMemoryEPKhmRKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEjPNS_6MemMapEPKNS_7OatFileEPS9_"_sym).as< const DexFile*(const uint8_t* dex_file, size_t size, const std::string& location, uint32_t location_checksum, void* mem_map, const void* oat_dex_file, - std::string* error_msg)> - OpenMemoryRaw_; + std::string* error_msg)>; - inline static Function< - {"_ZN3art7DexFile10OpenMemoryEPKhjRKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEjPNS_6MemMapEPS9_", - "_ZN3art7DexFile10OpenMemoryEPKhmRKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEjPNS_6MemMapEPS9_"}, + inline static auto OpenMemoryWithoutOdex_ = + ("_ZN3art7DexFile10OpenMemoryEPKhjRKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEjPNS_6MemMapEPS9_"_sym | + "_ZN3art7DexFile10OpenMemoryEPKhmRKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEjPNS_6MemMapEPS9_"_sym).as< const DexFile*(const uint8_t* dex_file, size_t size, const std::string& location, - uint32_t location_checksum, void* mem_map, std::string* error_msg)> - OpenMemoryWithoutOdex_; + uint32_t location_checksum, void* mem_map, std::string* error_msg)>; - inline static Function<"_ZN3artL18DexFile_setTrustedEP7_JNIEnvP7_jclassP8_jobject", - void(JNIEnv* env, jclass clazz, jobject j_cookie)> - DexFile_setTrusted_; + inline static auto DexFile_setTrusted_ = + "_ZN3artL18DexFile_setTrustedEP7_JNIEnvP7_jclassP8_jobject"_sym.as; public: static const DexFile* OpenMemory(const uint8_t* dex_file, size_t size, std::string location, 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 556dbad..90a35be 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 @@ -98,13 +98,10 @@ private: }; export class ScopedGCCriticalSection { - inline static MemberFunction< - "_ZN3art2gc23ScopedGCCriticalSectionC2EPNS_6ThreadENS0_7GcCauseENS0_13CollectorTypeE", - ScopedGCCriticalSection, void(Thread *, GcCause, CollectorType)> - constructor_; - inline static MemberFunction<"_ZN3art2gc23ScopedGCCriticalSectionD2Ev", ScopedGCCriticalSection, - void()> - destructor_; + inline static auto constructor_ = + "_ZN3art2gc23ScopedGCCriticalSectionC2EPNS_6ThreadENS0_7GcCauseENS0_13CollectorTypeE"_sym.as; + inline static auto destructor_ = + "_ZN3art2gc23ScopedGCCriticalSectionD2Ev"_sym.as; public: ScopedGCCriticalSection(Thread *self, GcCause cause, CollectorType collector_type) { diff --git a/lsplant/src/main/jni/art/runtime/instrumentation.cxx b/lsplant/src/main/jni/art/runtime/instrumentation.cxx index eb541ae..0d1840e 100644 --- a/lsplant/src/main/jni/art/runtime/instrumentation.cxx +++ b/lsplant/src/main/jni/art/runtime/instrumentation.cxx @@ -21,31 +21,28 @@ export class Instrumentation { return art_method; } - inline static MemberHooker< - "_ZN3art15instrumentation15Instrumentation40UpdateMethodsCodeToInterpreterEntryPointEPNS_9ArtMethodE", - Instrumentation, void(ArtMethod *)> - UpdateMethodsCodeToInterpreterEntryPoint_ = - +[](Instrumentation *thiz, ArtMethod *art_method) { - if (IsDeoptimized(art_method)) { - LOGV("skip update entrypoint on deoptimized method %s", - art_method->PrettyMethod(true).c_str()); - return; - } - UpdateMethodsCodeToInterpreterEntryPoint_( - thiz, MaybeUseBackupMethod(art_method, nullptr)); - }; - - inline static MemberHooker< - "_ZN3art15instrumentation15Instrumentation21InitializeMethodsCodeEPNS_9ArtMethodEPKv", - Instrumentation, void(ArtMethod *, const void *)> - InitializeMethodsCode_ = +[](Instrumentation *thiz, ArtMethod *art_method, - const void *quick_code) { + inline static auto UpdateMethodsCodeToInterpreterEntryPoint_ = + "_ZN3art15instrumentation15Instrumentation40UpdateMethodsCodeToInterpreterEntryPointEPNS_9ArtMethodE"_sym.hook->*[] + + (Instrumentation *thiz, ArtMethod *art_method) static -> void { if (IsDeoptimized(art_method)) { LOGV("skip update entrypoint on deoptimized method %s", art_method->PrettyMethod(true).c_str()); return; } - InitializeMethodsCode_(thiz, MaybeUseBackupMethod(art_method, quick_code), quick_code); + backup(thiz, MaybeUseBackupMethod(art_method, nullptr)); + }; + + inline static auto InitializeMethodsCode_ = + "_ZN3art15instrumentation15Instrumentation21InitializeMethodsCodeEPNS_9ArtMethodEPKv"_sym.hook->*[] + + (Instrumentation *thiz, ArtMethod *art_method, const void *quick_code) static -> void { + if (IsDeoptimized(art_method)) { + LOGV("skip update entrypoint on deoptimized method %s", + art_method->PrettyMethod(true).c_str()); + return; + } + backup(thiz, MaybeUseBackupMethod(art_method, quick_code), quick_code); }; public: diff --git a/lsplant/src/main/jni/art/runtime/jit/jit.cxx b/lsplant/src/main/jni/art/runtime/jit/jit.cxx index 010d705..2ae663f 100644 --- a/lsplant/src/main/jni/art/runtime/jit/jit.cxx +++ b/lsplant/src/main/jni/art/runtime/jit/jit.cxx @@ -17,29 +17,28 @@ enum class CompilationKind { }; export class Jit { - inline static MemberHooker< - "_ZN3art3jit3Jit27EnqueueOptimizedCompilationEPNS_9ArtMethodEPNS_6ThreadE", Jit, - void(ArtMethod *, Thread *)> - EnqueueOptimizedCompilation_ = +[](Jit *thiz, ArtMethod *method, Thread *self) { + inline static auto EnqueueOptimizedCompilation_ = + "_ZN3art3jit3Jit27EnqueueOptimizedCompilationEPNS_9ArtMethodEPNS_6ThreadE"_sym.hook->*[] + + (Jit *thiz, ArtMethod *method, Thread *self) static -> void { if (auto target = IsBackup(method); target) [[unlikely]] { LOGD("Propagate enqueue compilation: %p -> %p", method, target); method = target; } - return EnqueueOptimizedCompilation_(thiz, method, self); + return backup(thiz, method, self); }; - inline static MemberHooker< - "_ZN3art3jit3Jit14AddCompileTaskEPNS_6ThreadEPNS_9ArtMethodENS_15CompilationKindEb", Jit, - void(Thread *, ArtMethod *, CompilationKind, bool)> - AddCompileTask_ = +[](Jit *thiz, Thread *self, ArtMethod *method, - CompilationKind compilation_kind, bool precompile) { + inline static auto AddCompileTask_ = + "_ZN3art3jit3Jit14AddCompileTaskEPNS_6ThreadEPNS_9ArtMethodENS_15CompilationKindEb"_sym.hook->*[] + + (Jit *thiz, Thread *self, ArtMethod *method, CompilationKind compilation_kind, bool precompile) static -> void { if (compilation_kind == CompilationKind::kOptimized && !precompile) { - if (auto backup = IsHooked(method); backup) [[unlikely]] { - LOGD("Propagate compile task: %p -> %p", method, backup); - method = backup; + if (auto b = IsHooked(method); b) [[unlikely]] { + LOGD("Propagate compile task: %p -> %p", method, b); + method = b; } } - return AddCompileTask_(thiz, self, method, compilation_kind, precompile); + return backup(thiz, self, method, compilation_kind, precompile); }; public: 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 a5c78ac..886a15f 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 @@ -11,9 +11,8 @@ import hook_helper; namespace lsplant::art::jit { export class JitCodeCache { - inline static MemberFunction<"_ZN3art3jit12JitCodeCache18MoveObsoleteMethodEPNS_9ArtMethodES3_", - JitCodeCache, void(ArtMethod *, ArtMethod *)> - MoveObsoleteMethod_; + inline static auto MoveObsoleteMethod_ = + "_ZN3art3jit12JitCodeCache18MoveObsoleteMethodEPNS_9ArtMethodES3_"_sym.as; static void MoveObsoleteMethods(JitCodeCache *thiz) { auto movements = GetJitMovements(); @@ -28,18 +27,20 @@ export class JitCodeCache { } } - inline static MemberHooker<"_ZN3art3jit12JitCodeCache19GarbageCollectCacheEPNS_6ThreadE", - JitCodeCache, void(Thread *)> - GarbageCollectCache_ = +[](JitCodeCache *thiz, Thread *self) { + inline static auto GarbageCollectCache_ = + "_ZN3art3jit12JitCodeCache19GarbageCollectCacheEPNS_6ThreadE"_sym.hook->*[] + + (JitCodeCache *thiz, Thread *self) static -> void { MoveObsoleteMethods(thiz); - GarbageCollectCache_(thiz, self); + backup(thiz, self); }; - inline static MemberHooker<"_ZN3art3jit12JitCodeCache12DoCollectionEPNS_6ThreadE", JitCodeCache, - void(Thread *)> - DoCollection_ = +[](JitCodeCache *thiz, Thread *self) { + inline static auto DoCollection_ = + "_ZN3art3jit12JitCodeCache12DoCollectionEPNS_6ThreadE"_sym.hook->*[] + + (JitCodeCache *thiz, Thread *self) static -> void { MoveObsoleteMethods(thiz); - DoCollection_(thiz, self); + backup(thiz, self); }; public: 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 dceaae9..8c4d02b 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 @@ -13,16 +13,15 @@ namespace lsplant::art::jni { export class JniIdManager { private: - inline static MemberHooker< - "_ZN3art3jni12JniIdManager15EncodeGenericIdINS_9ArtMethodEEEmNS_16ReflectiveHandleIT_EE", - JniIdManager, uintptr_t(ReflectiveHandle)> - EncodeGenericId_ = - +[](JniIdManager *thiz, ReflectiveHandle method) -> uintptr_t { + inline static auto EncodeGenericId_ = + "_ZN3art3jni12JniIdManager15EncodeGenericIdINS_9ArtMethodEEEmNS_16ReflectiveHandleIT_EE"_sym.hook->*[] + + (JniIdManager *thiz, ReflectiveHandle method) static -> uintptr_t { if (auto target = IsBackup(method.Get()); target) { LOGD("get generic id for %s", method.Get()->PrettyMethod().c_str()); method.Set(target); } - return EncodeGenericId_(thiz, method); + return backup(thiz, method); }; public: diff --git a/lsplant/src/main/jni/art/runtime/runtime.cxx b/lsplant/src/main/jni/art/runtime/runtime.cxx index c46b8e4..54ee714 100644 --- a/lsplant/src/main/jni/art/runtime/runtime.cxx +++ b/lsplant/src/main/jni/art/runtime/runtime.cxx @@ -30,13 +30,13 @@ public: }; private: - inline static Field<"_ZN3art7Runtime9instance_E", Runtime *> instance_; + inline static auto instance_ = "_ZN3art7Runtime9instance_E"_sym.as; - inline static MemberFunction<"_ZN3art7Runtime17SetJavaDebuggableEb", Runtime, void(bool)> - SetJavaDebuggable_; - inline static MemberFunction<"_ZN3art7Runtime20SetRuntimeDebugStateENS0_17RuntimeDebugStateE", - Runtime, void(RuntimeDebugState)> - SetRuntimeDebugState_; + inline static auto SetJavaDebuggable_ = + "_ZN3art7Runtime17SetJavaDebuggableEb"_sym.as; + + inline static auto SetRuntimeDebugState_ = + "_ZN3art7Runtime20SetRuntimeDebugStateENS0_17RuntimeDebugStateE"_sym.as; inline static size_t debug_state_offset = 0U; diff --git a/lsplant/src/main/jni/art/runtime/thread.cxx b/lsplant/src/main/jni/art/runtime/thread.cxx index 9880d6d..2f3d8ed 100644 --- a/lsplant/src/main/jni/art/runtime/thread.cxx +++ b/lsplant/src/main/jni/art/runtime/thread.cxx @@ -6,7 +6,7 @@ import hook_helper; namespace lsplant::art { export class Thread { - inline static Function<"_ZN3art6Thread14CurrentFromGdbEv", Thread *()> CurrentFromGdb_; + inline static auto CurrentFromGdb_ = "_ZN3art6Thread14CurrentFromGdbEv"_sym.as; public: static Thread *Current() { diff --git a/lsplant/src/main/jni/art/runtime/thread_list.cxx b/lsplant/src/main/jni/art/runtime/thread_list.cxx index 95d0eb6..4cbaa24 100644 --- a/lsplant/src/main/jni/art/runtime/thread_list.cxx +++ b/lsplant/src/main/jni/art/runtime/thread_list.cxx @@ -7,14 +7,14 @@ import hook_helper; namespace lsplant::art::thread_list { export class ScopedSuspendAll { - inline static MemberFunction<"_ZN3art16ScopedSuspendAllC2EPKcb", ScopedSuspendAll, - void(const char *, bool)> - constructor_; - inline static MemberFunction<"_ZN3art16ScopedSuspendAllD2Ev", ScopedSuspendAll, void()> - destructor_; + inline static auto constructor_ = + "_ZN3art16ScopedSuspendAllC2EPKcb"_sym.as; - inline static Function<"_ZN3art3Dbg9SuspendVMEv", void()> SuspendVM_; - inline static Function<"_ZN3art3Dbg8ResumeVMEv", void()> ResumeVM_; + inline static auto destructor_ = + "_ZN3art16ScopedSuspendAllD2Ev"_sym.as; + + inline static auto SuspendVM_ = "_ZN3art3Dbg9SuspendVMEv"_sym.as; + inline static auto ResumeVM_ = "_ZN3art3Dbg8ResumeVMEv"_sym.as; public: ScopedSuspendAll(const char *cause, bool long_suspend) { diff --git a/lsplant/src/main/jni/include/utils/hook_helper.hpp b/lsplant/src/main/jni/include/utils/hook_helper.hpp index ad148a4..ac87d2b 100644 --- a/lsplant/src/main/jni/include/utils/hook_helper.hpp +++ b/lsplant/src/main/jni/include/utils/hook_helper.hpp @@ -22,79 +22,139 @@ struct FixedString { char data[N] = {}; }; -template +template +concept FuncType = std::is_function_v || std::is_member_function_pointer_v; + +template struct Function; -template -struct MemberFunction; +template +struct Function { + [[gnu::always_inline]] static Ret operator()(Args... args) { + return inner_.function_(args...); + } + [[gnu::always_inline]] operator bool() { return inner_.raw_function_; } + [[gnu::always_inline]] auto operator&() const { return inner_.function_; } + [[gnu::always_inline]] Function &operator=(void *function) { + inner_.raw_function_ = function; + return *this; + } + +private: + inline static union { + Ret (*function_)(Args...); + void *raw_function_ = nullptr; + } inner_; + + static_assert(sizeof(inner_.function_) == sizeof(inner_.raw_function_)); +}; + +template +struct Function { + [[gnu::always_inline]] static Ret operator()(This *thiz, Args... args) { + return (reinterpret_cast(thiz)->*inner_.function_)(args...); + } + [[gnu::always_inline]] operator bool() { return inner_.raw_function_; } + [[gnu::always_inline]] auto operator&() const { return inner_.function_; } + [[gnu::always_inline]] Function &operator=(void *function) { + inner_.raw_function_ = function; + return *this; + } + +private: + using ThisType = std::conditional_t, Function, This>; + inline static union { + Ret (ThisType::*function_)(Args...) const; + + struct { + void *raw_function_ = nullptr; + [[maybe_unused]] std::ptrdiff_t adj = 0; + }; + } inner_; + + static_assert(sizeof(inner_.function_) == sizeof(inner_.raw_function_) + sizeof(inner_.adj)); +}; template struct Field { - [[gnu::always_inline]] T *operator->() { return field_; } - [[gnu::always_inline]] T &operator*() { return *field_; } - [[gnu::always_inline]] operator bool() { return field_ != nullptr; } - + [[gnu::always_inline]] T *operator->() { return inner_.field_; } + [[gnu::always_inline]] T &operator*() { return *inner_.field_; } + [[gnu::always_inline]] operator bool() { return inner_.raw_field_ != nullptr; } + [[gnu::always_inline]] Field &operator=(void *field) { + inner_.raw_field_ = field; + return *this; + } private: - friend struct HookHandler; - T *field_; + inline static union { + void *raw_field_ = nullptr; + T *field_; + } inner_; + + static_assert(sizeof(inner_.field_) == sizeof(inner_.raw_field_)); }; -template +template struct Hooker; -template -struct MemberHooker; +template +struct Hooker : Function { + [[gnu::always_inline]] Hooker &operator=(void *function) { + Function::operator=(function); + return *this; + } +private: + [[gnu::always_inline]] constexpr Hooker(Ret (*replace)(Args...)) { + replace_ = replace; + }; + friend struct HookHandler; + template + friend struct Symbol; + inline static Ret (*replace_)(Args...) = nullptr; +}; -template - requires(std::is_same_v || std::is_same_v) -inline auto memfun_cast(Return (*func)(T *, Args...)) { - union { - Return (Class::*f)(Args...) const; - - struct { - decltype(func) p; - std::ptrdiff_t adj; - } data; - } u{.data = {func, 0}}; - static_assert(sizeof(u.f) == sizeof(u.data), "Try different T"); - return u.f; -} - -template T, typename Return, typename... Args> -inline auto memfun_cast(Return (*func)(T *, Args...)) { - return memfun_cast(func); -} +template +struct Hooker : Function { + [[gnu::always_inline]] Hooker &operator=(void *function) { + Function::operator=(function); + return *this; + } +private: + [[gnu::always_inline]] constexpr Hooker(Ret (*replace)(This *, Args...)) { + replace_ = replace; + }; + friend struct HookHandler; + template + friend struct Symbol; + inline static Ret (*replace_)(This *, Args...) = nullptr; +}; struct HookHandler { HookHandler(const InitInfo &info) : info_(info) {} template - [[gnu::always_inline]] bool dlsym(MemberFunction &function, + [[gnu::always_inline]] bool dlsym(Function &function, bool match_prefix = false) const { - return function.function_ = memfun_cast( - reinterpret_cast(dlsym(match_prefix))); + return function = dlsym(match_prefix); } template [[gnu::always_inline]] bool dlsym(Function &function, bool match_prefix = false) const { - return function.function_ = reinterpret_cast(dlsym(match_prefix)); + return function = dlsym(match_prefix); } template [[gnu::always_inline]] bool dlsym(Field &field, bool match_prefix = false) const { - return field.field_ = reinterpret_cast(dlsym(match_prefix)); + return field = dlsym(match_prefix); } template [[gnu::always_inline]] bool hook(Hooker &hooker) const { - return hooker.function_ = reinterpret_cast( - hook(dlsym(), reinterpret_cast(hooker.replace_))); + return hooker = hook(dlsym(), reinterpret_cast(hooker.replace_)); } template - [[gnu::always_inline]] bool hook(MemberHooker &hooker) const { - return hooker.function_ = memfun_cast(reinterpret_cast( - hook(dlsym(), reinterpret_cast(hooker.replace_)))); + [[gnu::always_inline]] bool hook(Hooker &hooker) const { + return hooker = hook(dlsym(), reinterpret_cast(hooker.replace_)); } template @@ -124,51 +184,77 @@ private: } }; -template -struct Function { - [[gnu::always_inline]] constexpr Ret operator()(Args... args) { return function_(args...); } - [[gnu::always_inline]] operator bool() { return function_ != nullptr; } - auto operator&() const { return function_; } - Function &operator=(void *function) { - function_ = reinterpret_cast(function); - return *this; + +struct Dummy; + +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()...))>(); } +}>); -private: - friend struct HookHandler; - Ret (*function_)(Args...) = nullptr; +template +struct Symbol { + template + inline static decltype([]{ + if constexpr (FuncType) { + return Function{}; + } else { + return Field{}; + } + }()) as{}; + + [[no_unique_address]] struct Hook { + template + requires(requires { std::declval>(); }) + auto operator->*(F&&) const { + 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; }; -template -struct MemberFunction { - [[gnu::always_inline]] constexpr Ret operator()(This *thiz, Args... args) { - return (reinterpret_cast(thiz)->*function_)(args...); - } - [[gnu::always_inline]] operator bool() { return function_ != nullptr; } +template constexpr Symbol operator""_sym() { + return {}; +} -private: - friend struct HookHandler; - using ThisType = std::conditional_t, MemberFunction, This>; - Ret (ThisType::*function_)(Args...) const = nullptr; -}; - -template -struct Hooker : Function { - [[gnu::always_inline]] constexpr Hooker(Ret (*replace)(Args...)) : replace_(replace) {}; - -private: - friend struct HookHandler; - [[maybe_unused]] Ret (*replace_)(Args...) = nullptr; -}; - -template -struct MemberHooker : MemberFunction { - [[gnu::always_inline]] constexpr MemberHooker(Ret (*replace)(This *, Args...)) - : replace_(replace) {}; - -private: - friend struct HookHandler; - [[maybe_unused]] Ret (*replace_)(This *, Args...) = nullptr; -}; +template +consteval auto operator|([[maybe_unused]] Symbol a, [[maybe_unused]] Symbol

b) { +#if defined(__LP64__) + return b; +#else + return a; +#endif +} +void test() { + "test"_sym.hook->*[](std::string *x) static -> char { + return backup(x); + }; +} } // namespace lsplant diff --git a/lsplant/src/main/jni/include/utils/hook_helper.ixx b/lsplant/src/main/jni/include/utils/hook_helper.ixx index c7887e4..41158ba 100644 --- a/lsplant/src/main/jni/include/utils/hook_helper.ixx +++ b/lsplant/src/main/jni/include/utils/hook_helper.ixx @@ -5,12 +5,10 @@ module; export module hook_helper; export namespace lsplant { -using lsplant::Field; using lsplant::FixedString; -using lsplant::Function; -using lsplant::Hooker; using lsplant::HookHandler; -using lsplant::MemberFunction; -using lsplant::MemberHooker; -using lsplant::memfun_cast; +using lsplant::operator""_sym; +using lsplant::Backup; +using lsplant::MemBackup; +using lsplant::operator|; } // namespace lsplant