mirror of
https://github.com/LSPosed/LSPlant.git
synced 2025-05-04 20:42:02 +08:00
Better native method hook
This commit is contained in:
parent
050561ac9a
commit
0c1cf50831
@ -36,12 +36,60 @@ private:
|
||||
return backup(art_method);
|
||||
});
|
||||
|
||||
inline static art::ArtMethod *MayGetBackup(art::ArtMethod *method) {
|
||||
std::shared_lock lk(hooked_methods_lock_);
|
||||
if (auto found = hooked_methods_.find(method); found != hooked_methods_.end())
|
||||
[[unlikely]] {
|
||||
method = found->second.second;
|
||||
LOGV("propagate native method: %s", method->PrettyMethod(true).data());
|
||||
}
|
||||
return method;
|
||||
}
|
||||
|
||||
CREATE_MEM_HOOK_STUB_ENTRY(
|
||||
"_ZN3art6mirror9ArtMethod14RegisterNativeEPNS_6ThreadEPKvb", void, RegisterNativeThread,
|
||||
(art::ArtMethod * method, art::Thread *thread, const void *native_method, bool is_fast),
|
||||
{ return backup(MayGetBackup(method), thread, native_method, is_fast); });
|
||||
|
||||
CREATE_MEM_HOOK_STUB_ENTRY("_ZN3art6mirror9ArtMethod16UnregisterNativeEPNS_6ThreadE", void,
|
||||
UnregisterNativeThread,
|
||||
(art::ArtMethod * method, art::Thread *thread),
|
||||
{ return backup(MayGetBackup(method), thread); });
|
||||
|
||||
CREATE_MEM_HOOK_STUB_ENTRY("_ZN3art9ArtMethod14RegisterNativeEPKvb", void, RegisterNativeFast,
|
||||
(art::ArtMethod * method, const void *native_method, bool is_fast),
|
||||
{ return backup(MayGetBackup(method), native_method, is_fast); });
|
||||
|
||||
CREATE_MEM_HOOK_STUB_ENTRY("_ZN3art9ArtMethod16UnregisterNativeEv", void, UnregisterNativeFast,
|
||||
(art::ArtMethod * method), { return backup(MayGetBackup(method)); });
|
||||
|
||||
CREATE_MEM_HOOK_STUB_ENTRY("_ZN3art9ArtMethod14RegisterNativeEPKv", const void *,
|
||||
RegisterNative, (art::ArtMethod * method, const void *native_method),
|
||||
{ return backup(MayGetBackup(method), native_method); });
|
||||
|
||||
CREATE_MEM_HOOK_STUB_ENTRY("_ZN3art9ArtMethod16UnregisterNativeEv", const void *,
|
||||
UnregisterNative, (art::ArtMethod * method),
|
||||
{ return backup(MayGetBackup(method)); });
|
||||
|
||||
CREATE_MEM_HOOK_STUB_ENTRY(
|
||||
"_ZN3art11ClassLinker14RegisterNativeEPNS_6ThreadEPNS_9ArtMethodEPKv", const void *,
|
||||
RegisterNativeClassLinker,
|
||||
(art::ClassLinker * thiz, art::Thread *self, art::ArtMethod *method,
|
||||
const void *native_method),
|
||||
{ return backup(thiz, self, MayGetBackup(method), native_method); });
|
||||
|
||||
CREATE_MEM_HOOK_STUB_ENTRY("_ZN3art11ClassLinker16UnregisterNativeEPNS_6ThreadEPNS_9ArtMethodE",
|
||||
const void *, UnregisterNativeClassLinker,
|
||||
(art::ClassLinker * thiz, art::Thread *self, art::ArtMethod *method),
|
||||
{ return backup(thiz, self, MayGetBackup(method)); });
|
||||
|
||||
static auto GetBackupMethods(mirror::Class *mirror_class) {
|
||||
std::list<std::tuple<art::ArtMethod *, void *>> out;
|
||||
auto class_def = mirror_class->GetClassDef();
|
||||
if (!class_def) return out;
|
||||
std::shared_lock lk(hooked_classes_lock_);
|
||||
if (auto found = hooked_classes_.find(class_def); found != hooked_classes_.end()) {
|
||||
if (auto found = hooked_classes_.find(class_def); found != hooked_classes_.end())
|
||||
[[unlikely]] {
|
||||
LOGD("Before fixup %s, backup hooked methods' trampoline",
|
||||
mirror_class->GetDescriptor().c_str());
|
||||
for (auto method : found->second) {
|
||||
@ -54,10 +102,13 @@ private:
|
||||
static void FixTrampoline(const std::list<std::tuple<art::ArtMethod *, void *>> &methods) {
|
||||
std::shared_lock lk(hooked_methods_lock_);
|
||||
for (const auto &[art_method, old_trampoline] : methods) {
|
||||
if (auto found = hooked_methods_.find(art_method); found != hooked_methods_.end()) {
|
||||
if (auto found = hooked_methods_.find(art_method); found != hooked_methods_.end())
|
||||
[[likely]] {
|
||||
auto &backup_method = found->second.second;
|
||||
if (auto new_trampoline = art_method->GetEntryPoint();
|
||||
new_trampoline != old_trampoline) {
|
||||
found->second.second->SetEntryPoint(new_trampoline);
|
||||
new_trampoline != old_trampoline) [[unlikely]] {
|
||||
LOGV("propagate entrypoint for %s", backup_method->PrettyMethod(true).data());
|
||||
backup_method->SetEntryPoint(new_trampoline);
|
||||
art_method->SetEntryPoint(old_trampoline);
|
||||
}
|
||||
}
|
||||
@ -105,6 +156,13 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!HookSyms(handler, RegisterNativeClassLinker, RegisterNative, RegisterNativeFast,
|
||||
RegisterNativeThread) ||
|
||||
!HookSyms(handler, UnregisterNativeClassLinker, UnregisterNative, UnregisterNativeFast,
|
||||
UnregisterNativeThread)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!RETRIEVE_MEM_FUNC_SYMBOL(
|
||||
SetEntryPointsToInterpreter,
|
||||
"_ZNK3art11ClassLinker27SetEntryPointsToInterpreterEPNS_9ArtMethodE"))
|
||||
|
@ -92,7 +92,7 @@ struct InitInfo {
|
||||
/// name, its field name, its source name and its method name by setting generated_* in \ref
|
||||
/// InitInfo.
|
||||
/// \note This function thread safe (you can call it simultaneously from multiple thread)
|
||||
/// but it's not atomic to the same \b target_method. That means #UnHook() or #IsUnhook() does not
|
||||
/// but it's not atomic to the same \b target_method. That means #UnHook() or #Ishook() does not
|
||||
/// guarantee to work properly on the same \p target_method before it returns. Also, simultaneously
|
||||
/// call on this function with the same \p target_method does not guarantee only one will success.
|
||||
/// If you call this with different \p hooker_object on the same target_method simultaneously, the
|
||||
|
Loading…
x
Reference in New Issue
Block a user