Fix static method hook lost if it is deoptimized before class initialization

This commit is contained in:
5ec1cff 2024-02-18 01:09:09 +08:00
parent e0e8cc11dc
commit 7ebe6b476a
No known key found for this signature in database
GPG Key ID: 609C383297F6FEBF
2 changed files with 13 additions and 12 deletions

View File

@ -27,21 +27,21 @@ private:
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());
}
}
});
@ -51,7 +51,7 @@ private:
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());
}
}
});

View File

@ -79,19 +79,20 @@ private:
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);
}
}
}
}