mirror of
https://github.com/LSPosed/LSPlant.git
synced 2025-05-04 20:42:02 +08:00
Fix static method hook lost if it is deoptimized before class initialization
This commit is contained in:
parent
e0e8cc11dc
commit
7ebe6b476a
@ -27,21 +27,21 @@ private:
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
using BackupMethods = std::list<std::tuple<art::ArtMethod *, void *>>;
|
using BackupMethods = phmap::flat_hash_map<art::ArtMethod *, void *>;
|
||||||
inline static phmap::flat_hash_map<const art::Thread *,
|
inline static phmap::flat_hash_map<const art::Thread *,
|
||||||
phmap::flat_hash_map<const dex::ClassDef *, BackupMethods>>
|
phmap::flat_hash_map<const dex::ClassDef *, BackupMethods>>
|
||||||
backup_methods_;
|
backup_methods_;
|
||||||
inline static std::mutex backup_methods_lock_;
|
inline static std::mutex backup_methods_lock_;
|
||||||
|
|
||||||
static void BackupClassMethods(const dex::ClassDef *class_def, art::Thread *self) {
|
static void BackupClassMethods(const dex::ClassDef *class_def, art::Thread *self) {
|
||||||
std::list<std::tuple<art::ArtMethod *, void *>> out;
|
BackupMethods out;
|
||||||
if (!class_def) return;
|
if (!class_def) return;
|
||||||
{
|
{
|
||||||
hooked_classes_.if_contains(class_def, [&out](const auto &it) {
|
hooked_classes_.if_contains(class_def, [&out](const auto &it) {
|
||||||
for (auto method : it.second) {
|
for (auto method : it.second) {
|
||||||
if (method->IsStatic()) {
|
if (method->IsStatic()) {
|
||||||
LOGV("Backup hooked method %p because of initialization", method);
|
LOGV("Backup hooked method %p because of initialization", method);
|
||||||
out.emplace_back(method, method->GetEntryPoint());
|
out.emplace(method, method->GetEntryPoint());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -51,7 +51,7 @@ private:
|
|||||||
for (auto method : it.second) {
|
for (auto method : it.second) {
|
||||||
if (method->IsStatic()) {
|
if (method->IsStatic()) {
|
||||||
LOGV("Backup deoptimized method %p because of initialization", method);
|
LOGV("Backup deoptimized method %p because of initialization", method);
|
||||||
out.emplace_back(method, method->GetEntryPoint());
|
out.emplace(method, method->GetEntryPoint());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -79,19 +79,20 @@ private:
|
|||||||
for (const auto &[art_method, old_trampoline] : methods) {
|
for (const auto &[art_method, old_trampoline] : methods) {
|
||||||
auto new_trampoline = art_method->GetEntryPoint();
|
auto new_trampoline = art_method->GetEntryPoint();
|
||||||
art_method->SetEntryPoint(old_trampoline);
|
art_method->SetEntryPoint(old_trampoline);
|
||||||
if (IsDeoptimized(art_method)) {
|
auto deoptimized = IsDeoptimized(art_method);
|
||||||
|
auto backup_method = IsHooked(art_method);
|
||||||
|
if (backup_method) {
|
||||||
|
// If deoptimized, the backup entrypoint should be already set to interpreter
|
||||||
|
if (!deoptimized && new_trampoline != old_trampoline) [[unlikely]] {
|
||||||
|
LOGV("propagate entrypoint for orig %p backup %p", art_method, backup_method);
|
||||||
|
backup_method->SetEntryPoint(new_trampoline);
|
||||||
|
}
|
||||||
|
} else if (deoptimized) {
|
||||||
if (new_trampoline != art_quick_to_interpreter_bridge &&
|
if (new_trampoline != art_quick_to_interpreter_bridge &&
|
||||||
new_trampoline != art_quick_generic_jni_trampoline) {
|
new_trampoline != art_quick_generic_jni_trampoline) {
|
||||||
LOGV("re-deoptimize for %p", art_method);
|
LOGV("re-deoptimize for %p", art_method);
|
||||||
SetEntryPointsToInterpreter(art_method);
|
SetEntryPointsToInterpreter(art_method);
|
||||||
}
|
}
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (auto backup_method = IsHooked(art_method); backup_method) [[likely]] {
|
|
||||||
if (new_trampoline != old_trampoline) [[unlikely]] {
|
|
||||||
LOGV("propagate entrypoint for %p", backup_method);
|
|
||||||
backup_method->SetEntryPoint(new_trampoline);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user