Refactor symbol define and use static operator() (#142)

This commit is contained in:
LoveSy 2025-03-05 14:49:47 +08:00 committed by GitHub
parent 4a2293e222
commit c54fb307f2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 375 additions and 304 deletions

View File

@ -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+")

View File

@ -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:

View File

@ -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_) {

View File

@ -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);
};

View File

@ -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,

View File

@ -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) {

View File

@ -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:

View File

@ -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:

View File

@ -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:

View File

@ -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:

View File

@ -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;

View File

@ -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() {

View File

@ -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) {

View File

@ -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 <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 <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 <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)>()...))>();
}
}>);
template<FixedString S>
struct Symbol {
template<typename T>
inline static decltype([]{
if constexpr (FuncType<T>) {
return Function<S, T>{};
} else {
return Field<S, T>{};
}
}()) as{};
[[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 S> constexpr Symbol<S> operator""_sym() {
return {};
}
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, FixedString P>
consteval auto operator|([[maybe_unused]] Symbol<S> a, [[maybe_unused]] Symbol<P> b) {
#if defined(__LP64__)
return b;
#else
return a;
#endif
}
[[gnu::always_inline]] operator bool() { return function_ != nullptr; }
private:
friend struct HookHandler;
using ThisType = std::conditional_t<std::is_same_v<This, void>, MemberFunction, This>;
Ret (ThisType::*function_)(Args...) const = nullptr;
void test() {
"test"_sym.hook->*[]<MemBackup auto backup>(std::string *x) static -> char {
return backup(x);
};
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) {};
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;
};
}
} // namespace lsplant

View File

@ -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