mirror of
https://github.com/LSPosed/LSPlant.git
synced 2025-05-04 20:42:02 +08:00
Refactor symbol define and use static operator() (#142)
This commit is contained in:
parent
4a2293e222
commit
c54fb307f2
@ -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+")
|
||||
|
@ -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<const char *(Class::*)(std::string *)>;
|
||||
|
||||
inline static MemberFunction<"_ZN3art6mirror5Class11GetClassDefEv", Class,
|
||||
const dex::ClassDef *()>
|
||||
GetClassDef_;
|
||||
inline static auto GetClassDef_ =
|
||||
"_ZN3art6mirror5Class11GetClassDefEv"_sym.as<const dex::ClassDef *(Class::*)()>;
|
||||
|
||||
using BackupMethods = phmap::flat_hash_map<art::ArtMethod *, void *>;
|
||||
inline static phmap::flat_hash_map<const art::Thread *,
|
||||
@ -62,41 +59,44 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
inline static Hooker<
|
||||
"_ZN3art6mirror5Class9SetStatusENS_6HandleIS1_EENS_11ClassStatusEPNS_6ThreadE",
|
||||
void(TrivialHandle<Class>, uint8_t, Thread *)>
|
||||
SetClassStatus_ = +[](TrivialHandle<Class> h, uint8_t new_status, Thread *self) {
|
||||
inline static auto SetClassStatus_ =
|
||||
"_ZN3art6mirror5Class9SetStatusENS_6HandleIS1_EENS_11ClassStatusEPNS_6ThreadE"_sym.hook->*[]
|
||||
<Backup auto backup>
|
||||
(TrivialHandle<Class> 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<Class>, int, Thread *)>
|
||||
SetStatus_ = +[](Handle<Class> h, int new_status, Thread *self) {
|
||||
inline static auto SetStatus_ =
|
||||
"_ZN3art6mirror5Class9SetStatusENS_6HandleIS1_EENS1_6StatusEPNS_6ThreadE"_sym.hook->*[]
|
||||
<Backup auto backup>
|
||||
(Handle<Class> h, int new_status, Thread *self) static -> void {
|
||||
if (new_status == static_cast<int>(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<Class>, uint32_t, Thread *)>
|
||||
TrivialSetStatus_ = +[](TrivialHandle<Class> h, uint32_t new_status, Thread *self) {
|
||||
inline static auto TrivialSetStatus_ =
|
||||
"_ZN3art6mirror5Class9SetStatusENS_6HandleIS1_EENS1_6StatusEPNS_6ThreadE"_sym.hook->*[]
|
||||
<Backup auto backup>
|
||||
(TrivialHandle<Class> 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->*[]
|
||||
<MemBackup auto backup>
|
||||
(Class *thiz, int new_status, Thread *self) static -> void {
|
||||
if (new_status == static_cast<int>(initialized_status)) {
|
||||
BackupClassMethods(GetClassDef_(thiz), self);
|
||||
}
|
||||
return ClassSetStatus_(thiz, new_status, self);
|
||||
return backup(thiz, new_status, self);
|
||||
};
|
||||
|
||||
public:
|
||||
|
@ -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<std::string(ArtMethod::*)(bool)>;
|
||||
|
||||
inline static Function<"_ZN3art12PrettyMethodEPNS_9ArtMethodEb",
|
||||
std::string(ArtMethod *thiz, bool with_signature)>
|
||||
PrettyMethodStatic_;
|
||||
inline static auto PrettyMethodStatic_ =
|
||||
"_ZN3art12PrettyMethodEPNS_9ArtMethodEb"_sym.as<std::string(ArtMethod *thiz, bool with_signature)>;
|
||||
|
||||
inline static Function<"_ZN3art12PrettyMethodEPNS_6mirror9ArtMethodEb",
|
||||
std::string(ArtMethod *thiz, bool with_signature)>
|
||||
PrettyMethodMirror_;
|
||||
inline static auto PrettyMethodMirror_ =
|
||||
"_ZN3art12PrettyMethodEPNS_6mirror9ArtMethodEb"_sym.as<std::string(ArtMethod *thiz, bool with_signature)>;
|
||||
|
||||
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<const char *(JNIEnv *env, jmethodID method)>;
|
||||
|
||||
inline static MemberFunction<"_ZN3art9ArtMethod24ThrowInvocationTimeErrorEv", ArtMethod, void()>
|
||||
ThrowInvocationTimeError_;
|
||||
inline static auto GetMethodShorty_ =
|
||||
"_ZN3art15GetMethodShortyEP7_JNIEnvP10_jmethodID"_sym.as<const char *(JNIEnv *env, jmethodID mid)>;
|
||||
|
||||
inline static Function<"artInterpreterToCompiledCodeBridge", void()>
|
||||
art_interpreter_to_compiled_code_bridge_;
|
||||
inline static auto ThrowInvocationTimeError_ =
|
||||
"_ZN3art9ArtMethod24ThrowInvocationTimeErrorEv"_sym.as<void(ArtMethod::*)()>;
|
||||
|
||||
inline static auto art_interpreter_to_compiled_code_bridge_ =
|
||||
"artInterpreterToCompiledCodeBridge"_sym.as<void()>;
|
||||
|
||||
inline void ThrowInvocationTimeError() {
|
||||
if (ThrowInvocationTimeError_) {
|
||||
|
@ -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<void(ClassLinker::*)(ArtMethod *)>;
|
||||
|
||||
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->*[]
|
||||
<Backup auto backup>
|
||||
(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<void(void *)>;
|
||||
|
||||
inline static Function<"_ZN3art15instrumentationL19GetOptimizedCodeForEPNS_9ArtMethodE",
|
||||
void *(ArtMethod *)> GetOptimizedCodeFor_;
|
||||
inline static auto GetOptimizedCodeFor_ =
|
||||
"_ZN3art15instrumentationL19GetOptimizedCodeForEPNS_9ArtMethodE"_sym.as<void *(ArtMethod *)>;
|
||||
|
||||
inline static MemberFunction<"_ZNK3art11ClassLinker29GetRuntimeQuickGenericJniStubEv",
|
||||
ClassLinker, void *()> GetRuntimeQuickGenericJniStub_;
|
||||
inline static auto GetRuntimeQuickGenericJniStub_=
|
||||
"_ZNK3art11ClassLinker29GetRuntimeQuickGenericJniStubEv"_sym.as<void *(ClassLinker::*)()>;
|
||||
|
||||
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->*[]
|
||||
<MemBackup auto backup>
|
||||
(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->*[]
|
||||
<MemBackup auto backup>
|
||||
(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 auto RegisterNativeFast_ =
|
||||
"_ZN3art9ArtMethod14RegisterNativeEPKvb"_sym.hook->*[]
|
||||
<MemBackup auto backup>
|
||||
(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<"_ZN3art9ArtMethod16UnregisterNativeEv", ClassLinker,
|
||||
void(ArtMethod *)>
|
||||
UnregisterNativeFast_ = +[](ClassLinker *thiz, ArtMethod *method) {
|
||||
return UnregisterNativeFast_(thiz, MayGetBackup(method));
|
||||
inline static auto UnregisterNativeFast_ =
|
||||
"_ZN3art9ArtMethod16UnregisterNativeEv"_sym.hook->*[]
|
||||
<MemBackup auto backup>
|
||||
(ClassLinker *thiz, ArtMethod *method) static -> void{
|
||||
return backup(thiz, MayGetBackup(method));
|
||||
};
|
||||
|
||||
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 RegisterNative_ =
|
||||
"_ZN3art9ArtMethod14RegisterNativeEPKv"_sym.hook->*[]
|
||||
<MemBackup auto backup>
|
||||
(ClassLinker *thiz, ArtMethod *method, const void *native_method) static -> const void * {
|
||||
return backup(thiz, MayGetBackup(method), native_method);
|
||||
};
|
||||
|
||||
inline static MemberHooker<"_ZN3art9ArtMethod16UnregisterNativeEv", ClassLinker,
|
||||
const void *(ArtMethod *)>
|
||||
UnregisterNative_ = +[](ClassLinker *thiz, ArtMethod *method) {
|
||||
return UnregisterNative_(thiz, MayGetBackup(method));
|
||||
inline static auto UnregisterNative_ =
|
||||
"_ZN3art9ArtMethod16UnregisterNativeEv"_sym.hook->*[]
|
||||
<MemBackup auto backup>
|
||||
(ClassLinker *thiz, ArtMethod *method) static -> const void * {
|
||||
return backup(thiz, MayGetBackup(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 RegisterNativeClassLinker_ =
|
||||
"_ZN3art11ClassLinker14RegisterNativeEPNS_6ThreadEPNS_9ArtMethodEPKv"_sym.hook->*[]
|
||||
<MemBackup auto backup>
|
||||
(ClassLinker *thiz, Thread *self, ArtMethod *method, const void *native_method) static -> const void *{
|
||||
return backup(thiz, self, MayGetBackup(method), native_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 UnregisterNativeClassLinker_ =
|
||||
"_ZN3art11ClassLinker16UnregisterNativeEPNS_6ThreadEPNS_9ArtMethodE"_sym.hook->*[]
|
||||
<MemBackup auto backup>
|
||||
(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<mirror::Class>)>
|
||||
FixupStaticTrampolines_ = +[](ClassLinker *thiz, ObjPtr<mirror::Class> mirror_class) {
|
||||
FixupStaticTrampolines_(thiz, mirror_class);
|
||||
inline static auto FixupStaticTrampolines_ =
|
||||
"_ZN3art11ClassLinker22FixupStaticTrampolinesENS_6ObjPtrINS_6mirror5ClassEEE"_sym.hook->*[]
|
||||
<MemBackup auto backup>
|
||||
(ClassLinker *thiz, ObjPtr<mirror::Class> mirror_class) static -> void {
|
||||
backup(thiz, mirror_class);
|
||||
RestoreBackup(mirror_class->GetClassDef(), nullptr);
|
||||
};
|
||||
|
||||
inline static MemberHooker<
|
||||
"_ZN3art11ClassLinker22FixupStaticTrampolinesEPNS_6ThreadENS_6ObjPtrINS_6mirror5ClassEEE",
|
||||
ClassLinker, void(Thread *, ObjPtr<mirror::Class>)>
|
||||
FixupStaticTrampolinesWithThread_ =
|
||||
+[](ClassLinker *thiz, Thread *self, ObjPtr<mirror::Class> mirror_class) {
|
||||
FixupStaticTrampolinesWithThread_(thiz, self, mirror_class);
|
||||
inline static auto FixupStaticTrampolinesWithThread_ =
|
||||
"_ZN3art11ClassLinker22FixupStaticTrampolinesEPNS_6ThreadENS_6ObjPtrINS_6mirror5ClassEEE"_sym.hook->*[]
|
||||
<MemBackup auto backup>
|
||||
(ClassLinker *thiz, Thread *self, ObjPtr<mirror::Class> 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->*[]
|
||||
<MemBackup auto backup>
|
||||
(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->*[]
|
||||
<MemBackup auto backup>
|
||||
(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->*[]
|
||||
<MemBackup auto backup>
|
||||
(ClassLinker *thiz, Thread *self) static -> void {
|
||||
backup(thiz, self);
|
||||
RestoreBackup(nullptr, self);
|
||||
};
|
||||
|
||||
|
@ -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<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)>
|
||||
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<void(JNIEnv* env, jclass clazz, jobject j_cookie)>;
|
||||
|
||||
public:
|
||||
static const DexFile* OpenMemory(const uint8_t* dex_file, size_t size, std::string location,
|
||||
|
@ -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<void(ScopedGCCriticalSection::*)(Thread *, GcCause, CollectorType)>;
|
||||
inline static auto destructor_ =
|
||||
"_ZN3art2gc23ScopedGCCriticalSectionD2Ev"_sym.as<void(ScopedGCCriticalSection::*)()>;
|
||||
|
||||
public:
|
||||
ScopedGCCriticalSection(Thread *self, GcCause cause, CollectorType collector_type) {
|
||||
|
@ -21,31 +21,28 @@ export class Instrumentation {
|
||||
return art_method;
|
||||
}
|
||||
|
||||
inline static MemberHooker<
|
||||
"_ZN3art15instrumentation15Instrumentation40UpdateMethodsCodeToInterpreterEntryPointEPNS_9ArtMethodE",
|
||||
Instrumentation, void(ArtMethod *)>
|
||||
UpdateMethodsCodeToInterpreterEntryPoint_ =
|
||||
+[](Instrumentation *thiz, ArtMethod *art_method) {
|
||||
inline static auto UpdateMethodsCodeToInterpreterEntryPoint_ =
|
||||
"_ZN3art15instrumentation15Instrumentation40UpdateMethodsCodeToInterpreterEntryPointEPNS_9ArtMethodE"_sym.hook->*[]
|
||||
<MemBackup auto backup>
|
||||
(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;
|
||||
}
|
||||
UpdateMethodsCodeToInterpreterEntryPoint_(
|
||||
thiz, MaybeUseBackupMethod(art_method, nullptr));
|
||||
backup(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 InitializeMethodsCode_ =
|
||||
"_ZN3art15instrumentation15Instrumentation21InitializeMethodsCodeEPNS_9ArtMethodEPKv"_sym.hook->*[]
|
||||
<MemBackup auto backup>
|
||||
(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;
|
||||
}
|
||||
InitializeMethodsCode_(thiz, MaybeUseBackupMethod(art_method, quick_code), quick_code);
|
||||
backup(thiz, MaybeUseBackupMethod(art_method, quick_code), quick_code);
|
||||
};
|
||||
|
||||
public:
|
||||
|
@ -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->*[]
|
||||
<MemBackup auto backup>
|
||||
(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->*[]
|
||||
<MemBackup auto backup>
|
||||
(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:
|
||||
|
@ -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<void(JitCodeCache::*)(ArtMethod *, ArtMethod *)>;
|
||||
|
||||
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->*[]
|
||||
<MemBackup auto backup>
|
||||
(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->*[]
|
||||
<MemBackup auto backup>
|
||||
(JitCodeCache *thiz, Thread *self) static -> void {
|
||||
MoveObsoleteMethods(thiz);
|
||||
DoCollection_(thiz, self);
|
||||
backup(thiz, self);
|
||||
};
|
||||
|
||||
public:
|
||||
|
@ -13,16 +13,15 @@ namespace lsplant::art::jni {
|
||||
|
||||
export class JniIdManager {
|
||||
private:
|
||||
inline static MemberHooker<
|
||||
"_ZN3art3jni12JniIdManager15EncodeGenericIdINS_9ArtMethodEEEmNS_16ReflectiveHandleIT_EE",
|
||||
JniIdManager, uintptr_t(ReflectiveHandle<ArtMethod>)>
|
||||
EncodeGenericId_ =
|
||||
+[](JniIdManager *thiz, ReflectiveHandle<ArtMethod> method) -> uintptr_t {
|
||||
inline static auto EncodeGenericId_ =
|
||||
"_ZN3art3jni12JniIdManager15EncodeGenericIdINS_9ArtMethodEEEmNS_16ReflectiveHandleIT_EE"_sym.hook->*[]
|
||||
<MemBackup auto backup>
|
||||
(JniIdManager *thiz, ReflectiveHandle<ArtMethod> 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:
|
||||
|
@ -30,13 +30,13 @@ public:
|
||||
};
|
||||
|
||||
private:
|
||||
inline static Field<"_ZN3art7Runtime9instance_E", Runtime *> instance_;
|
||||
inline static auto instance_ = "_ZN3art7Runtime9instance_E"_sym.as<Runtime *>;
|
||||
|
||||
inline static MemberFunction<"_ZN3art7Runtime17SetJavaDebuggableEb", Runtime, void(bool)>
|
||||
SetJavaDebuggable_;
|
||||
inline static MemberFunction<"_ZN3art7Runtime20SetRuntimeDebugStateENS0_17RuntimeDebugStateE",
|
||||
Runtime, void(RuntimeDebugState)>
|
||||
SetRuntimeDebugState_;
|
||||
inline static auto SetJavaDebuggable_ =
|
||||
"_ZN3art7Runtime17SetJavaDebuggableEb"_sym.as<void (Runtime::*)(bool)>;
|
||||
|
||||
inline static auto SetRuntimeDebugState_ =
|
||||
"_ZN3art7Runtime20SetRuntimeDebugStateENS0_17RuntimeDebugStateE"_sym.as<void (Runtime::*)(RuntimeDebugState)>;
|
||||
|
||||
inline static size_t debug_state_offset = 0U;
|
||||
|
||||
|
@ -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<Thread *()>;
|
||||
|
||||
public:
|
||||
static Thread *Current() {
|
||||
|
@ -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<void(ScopedSuspendAll::*)(const char *, bool)>;
|
||||
|
||||
inline static Function<"_ZN3art3Dbg9SuspendVMEv", void()> SuspendVM_;
|
||||
inline static Function<"_ZN3art3Dbg8ResumeVMEv", void()> ResumeVM_;
|
||||
inline static auto destructor_ =
|
||||
"_ZN3art16ScopedSuspendAllD2Ev"_sym.as<void(ScopedSuspendAll::*)()>;
|
||||
|
||||
inline static auto SuspendVM_ = "_ZN3art3Dbg9SuspendVMEv"_sym.as<void()>;
|
||||
inline static auto ResumeVM_ = "_ZN3art3Dbg8ResumeVMEv"_sym.as<void()>;
|
||||
|
||||
public:
|
||||
ScopedSuspendAll(const char *cause, bool long_suspend) {
|
||||
|
@ -22,79 +22,139 @@ struct FixedString {
|
||||
char data[N] = {};
|
||||
};
|
||||
|
||||
template <FixedString, typename>
|
||||
template<typename T>
|
||||
concept FuncType = std::is_function_v<T> || std::is_member_function_pointer_v<T>;
|
||||
|
||||
template <FixedString, FuncType>
|
||||
struct Function;
|
||||
|
||||
template <FixedString, typename, typename>
|
||||
struct MemberFunction;
|
||||
template <FixedString Sym, typename Ret, typename... Args>
|
||||
struct Function<Sym, Ret(Args...)> {
|
||||
[[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 <FixedString Sym, class This, typename Ret, typename... Args>
|
||||
struct Function<Sym, Ret(This::*)(Args...)> {
|
||||
[[gnu::always_inline]] static Ret operator()(This *thiz, Args... args) {
|
||||
return (reinterpret_cast<ThisType *>(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<std::is_same_v<This, void>, 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 <FixedString, typename T>
|
||||
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;
|
||||
inline static union {
|
||||
void *raw_field_ = nullptr;
|
||||
T *field_;
|
||||
} inner_;
|
||||
|
||||
static_assert(sizeof(inner_.field_) == sizeof(inner_.raw_field_));
|
||||
};
|
||||
|
||||
template <FixedString, typename>
|
||||
template <FixedString, FuncType>
|
||||
struct Hooker;
|
||||
|
||||
template <FixedString, typename, typename>
|
||||
struct MemberHooker;
|
||||
template <FixedString Sym, typename Ret, typename... Args>
|
||||
struct Hooker<Sym, Ret(Args...)> : Function<Sym, Ret(Args...)> {
|
||||
[[gnu::always_inline]] Hooker &operator=(void *function) {
|
||||
Function<Sym, Ret(Args...)>::operator=(function);
|
||||
return *this;
|
||||
}
|
||||
private:
|
||||
[[gnu::always_inline]] constexpr Hooker(Ret (*replace)(Args...)) {
|
||||
replace_ = replace;
|
||||
};
|
||||
friend struct HookHandler;
|
||||
template<FixedString S>
|
||||
friend struct Symbol;
|
||||
inline static Ret (*replace_)(Args...) = nullptr;
|
||||
};
|
||||
|
||||
template <typename Class, typename Return, typename T, typename... Args>
|
||||
requires(std::is_same_v<T, void> || std::is_same_v<Class, T>)
|
||||
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 <std::same_as<void> T, typename Return, typename... Args>
|
||||
inline auto memfun_cast(Return (*func)(T *, Args...)) {
|
||||
return memfun_cast<T>(func);
|
||||
}
|
||||
template <FixedString Sym, class This, typename Ret, typename... Args>
|
||||
struct Hooker<Sym, Ret(This::*)(Args...)> : Function<Sym, Ret(This::*)(Args...)> {
|
||||
[[gnu::always_inline]] Hooker &operator=(void *function) {
|
||||
Function<Sym, Ret(This::*)(Args...)>::operator=(function);
|
||||
return *this;
|
||||
}
|
||||
private:
|
||||
[[gnu::always_inline]] constexpr Hooker(Ret (*replace)(This *, Args...)) {
|
||||
replace_ = replace;
|
||||
};
|
||||
friend struct HookHandler;
|
||||
template<FixedString S>
|
||||
friend struct Symbol;
|
||||
inline static Ret (*replace_)(This *, Args...) = nullptr;
|
||||
};
|
||||
|
||||
struct HookHandler {
|
||||
HookHandler(const InitInfo &info) : info_(info) {}
|
||||
template <FixedString Sym, typename This, typename Ret, typename... Args>
|
||||
[[gnu::always_inline]] bool dlsym(MemberFunction<Sym, This, Ret(Args...)> &function,
|
||||
[[gnu::always_inline]] bool dlsym(Function<Sym, Ret(This::*)(Args...)> &function,
|
||||
bool match_prefix = false) const {
|
||||
return function.function_ = memfun_cast<This>(
|
||||
reinterpret_cast<Ret (*)(This *, Args...)>(dlsym<Sym>(match_prefix)));
|
||||
return function = dlsym<Sym>(match_prefix);
|
||||
}
|
||||
|
||||
template <FixedString Sym, typename Ret, typename... Args>
|
||||
[[gnu::always_inline]] bool dlsym(Function<Sym, Ret(Args...)> &function,
|
||||
bool match_prefix = false) const {
|
||||
return function.function_ = reinterpret_cast<Ret (*)(Args...)>(dlsym<Sym>(match_prefix));
|
||||
return function = dlsym<Sym>(match_prefix);
|
||||
}
|
||||
|
||||
template <FixedString Sym, typename T>
|
||||
[[gnu::always_inline]] bool dlsym(Field<Sym, T> &field, bool match_prefix = false) const {
|
||||
return field.field_ = reinterpret_cast<T *>(dlsym<Sym>(match_prefix));
|
||||
return field = dlsym<Sym>(match_prefix);
|
||||
}
|
||||
|
||||
template <FixedString Sym, typename Ret, typename... Args>
|
||||
[[gnu::always_inline]] bool hook(Hooker<Sym, Ret(Args...)> &hooker) const {
|
||||
return hooker.function_ = reinterpret_cast<Ret (*)(Args...)>(
|
||||
hook(dlsym<Sym>(), reinterpret_cast<void *>(hooker.replace_)));
|
||||
return hooker = hook(dlsym<Sym>(), reinterpret_cast<void *>(hooker.replace_));
|
||||
}
|
||||
|
||||
template <FixedString Sym, typename This, typename Ret, typename... Args>
|
||||
[[gnu::always_inline]] bool hook(MemberHooker<Sym, This, Ret(Args...)> &hooker) const {
|
||||
return hooker.function_ = memfun_cast<This>(reinterpret_cast<Ret (*)(This *, Args...)>(
|
||||
hook(dlsym<Sym>(), reinterpret_cast<void *>(hooker.replace_))));
|
||||
[[gnu::always_inline]] bool hook(Hooker<Sym, Ret(This::*)(Args...)> &hooker) const {
|
||||
return hooker = hook(dlsym<Sym>(), reinterpret_cast<void *>(hooker.replace_));
|
||||
}
|
||||
|
||||
template <typename T1, typename T2, typename... U>
|
||||
@ -124,51 +184,77 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
template <FixedString Sym, typename Ret, typename... Args>
|
||||
struct Function<Sym, Ret(Args...)> {
|
||||
[[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<decltype(function_)>(function);
|
||||
return *this;
|
||||
|
||||
struct Dummy;
|
||||
|
||||
template<typename F>
|
||||
concept Backup = std::is_function_v<std::remove_pointer_t<F>> || requires(F&& f) { { f(std::declval<Dummy*>()) } -> std::same_as<Dummy*>; };
|
||||
|
||||
template<typename F>
|
||||
concept MemBackup = std::is_function_v<std::remove_pointer_t<F>> || requires(F&& f) { { f(std::declval<Dummy*>()) } -> std::same_as<Dummy**>; };
|
||||
|
||||
template <typename T>
|
||||
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<F>
|
||||
template<typename F, bool mem>
|
||||
using Signature = decltype(F::template operator()<[](auto...a) static {
|
||||
using D = std::conditional_t<mem, Dummy**, Dummy*>;
|
||||
if constexpr ((false || ... || std::is_same_v<decltype(a), Dummy*>)) {
|
||||
return return_t<D>();
|
||||
} else {
|
||||
return return_t<decltype(F::template operator()<[](auto...) -> D {}>(std::declval<decltype(a)>()...))>();
|
||||
}
|
||||
}>);
|
||||
|
||||
private:
|
||||
friend struct HookHandler;
|
||||
Ret (*function_)(Args...) = nullptr;
|
||||
};
|
||||
|
||||
template <FixedString Sym, typename This, typename Ret, typename... Args>
|
||||
struct MemberFunction<Sym, This, Ret(Args...)> {
|
||||
[[gnu::always_inline]] constexpr Ret operator()(This *thiz, Args... args) {
|
||||
return (reinterpret_cast<ThisType *>(thiz)->*function_)(args...);
|
||||
template<FixedString S>
|
||||
struct Symbol {
|
||||
template<typename T>
|
||||
inline static decltype([]{
|
||||
if constexpr (FuncType<T>) {
|
||||
return Function<S, T>{};
|
||||
} else {
|
||||
return Field<S, T>{};
|
||||
}
|
||||
[[gnu::always_inline]] operator bool() { return function_ != nullptr; }
|
||||
}()) as{};
|
||||
|
||||
private:
|
||||
friend struct HookHandler;
|
||||
using ThisType = std::conditional_t<std::is_same_v<This, void>, MemberFunction, This>;
|
||||
Ret (ThisType::*function_)(Args...) const = nullptr;
|
||||
[[no_unique_address]] struct Hook {
|
||||
template<typename F>
|
||||
requires(requires { std::declval<Signature<F, false>>(); })
|
||||
auto operator->*(F&&) const {
|
||||
using HookerType = Hooker<S, Signature<F, false>>;
|
||||
return HookerType{static_cast<decltype(HookerType::replace_)>(&F::template operator()<HookerType::operator()>)};
|
||||
};
|
||||
template<typename F>
|
||||
requires(requires { std::declval<Signature<F, true>>(); })
|
||||
auto operator->*(F&&) const {
|
||||
constexpr auto c = []<class This, typename Ret, typename... Args>(Ret(*f)(This*, Args...)) -> Ret(This::*)(Args...) {
|
||||
return {};
|
||||
};
|
||||
using HookerType = Hooker<S, decltype(c.template operator()(std::declval<Signature<F, true>>()))>;
|
||||
return HookerType{static_cast<decltype(HookerType::replace_)>(&F::template operator()<HookerType::operator()>)};
|
||||
};
|
||||
|
||||
} hook;
|
||||
};
|
||||
|
||||
template <FixedString Sym, typename Ret, typename... Args>
|
||||
struct Hooker<Sym, Ret(Args...)> : Function<Sym, Ret(Args...)> {
|
||||
[[gnu::always_inline]] constexpr Hooker(Ret (*replace)(Args...)) : replace_(replace) {};
|
||||
template <FixedString S> constexpr Symbol<S> operator""_sym() {
|
||||
return {};
|
||||
}
|
||||
|
||||
private:
|
||||
friend struct HookHandler;
|
||||
[[maybe_unused]] Ret (*replace_)(Args...) = nullptr;
|
||||
};
|
||||
|
||||
template <FixedString Sym, typename This, typename Ret, typename... Args>
|
||||
struct MemberHooker<Sym, This, Ret(Args...)> : MemberFunction<Sym, This, Ret(Args...)> {
|
||||
[[gnu::always_inline]] constexpr MemberHooker(Ret (*replace)(This *, Args...))
|
||||
: replace_(replace) {};
|
||||
|
||||
private:
|
||||
friend struct HookHandler;
|
||||
[[maybe_unused]] Ret (*replace_)(This *, Args...) = nullptr;
|
||||
};
|
||||
template<FixedString S, FixedString P>
|
||||
consteval auto operator|([[maybe_unused]] Symbol<S> a, [[maybe_unused]] Symbol<P> b) {
|
||||
#if defined(__LP64__)
|
||||
return b;
|
||||
#else
|
||||
return a;
|
||||
#endif
|
||||
}
|
||||
|
||||
void test() {
|
||||
"test"_sym.hook->*[]<MemBackup auto backup>(std::string *x) static -> char {
|
||||
return backup(x);
|
||||
};
|
||||
}
|
||||
} // namespace lsplant
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user