Skip to content

Commit

Permalink
Fix static method hook lost if it is deoptimized before class initial…
Browse files Browse the repository at this point in the history
…ization
  • Loading branch information
5ec1cff committed Feb 17, 2024
1 parent e0e8cc1 commit 7ebe6b4
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 12 deletions.
8 changes: 4 additions & 4 deletions lsplant/src/main/jni/art/mirror/class.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,21 @@ class Class {
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 *,
phmap::flat_hash_map<const dex::ClassDef *, BackupMethods>>
backup_methods_;
inline static std::mutex backup_methods_lock_;

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;
{
hooked_classes_.if_contains(class_def, [&out](const auto &it) {
for (auto method : it.second) {
if (method->IsStatic()) {
LOGV("Backup hooked method %p because of initialization", method);
out.emplace_back(method, method->GetEntryPoint());
out.emplace(method, method->GetEntryPoint());
}
}
});
Expand All @@ -51,7 +51,7 @@ class Class {
for (auto method : it.second) {
if (method->IsStatic()) {
LOGV("Backup deoptimized method %p because of initialization", method);
out.emplace_back(method, method->GetEntryPoint());
out.emplace(method, method->GetEntryPoint());
}
}
});
Expand Down
17 changes: 9 additions & 8 deletions lsplant/src/main/jni/art/runtime/class_linker.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,19 +79,20 @@ class ClassLinker {
for (const auto &[art_method, old_trampoline] : methods) {
auto new_trampoline = art_method->GetEntryPoint();
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 &&
new_trampoline != art_quick_generic_jni_trampoline) {
LOGV("re-deoptimize for %p", 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);
}
}
}
}
Expand Down

0 comments on commit 7ebe6b4

Please sign in to comment.