[core] Fix stop the world in R (#130)

* [core] Fix wait for GC in R for Yahfa

* [core] Fix Sandhook stop the world
This commit is contained in:
LoveSy 2021-02-13 22:54:04 +08:00 committed by GitHub
parent 8abf2bd86b
commit 7db7b62ab6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 370 additions and 280 deletions

View File

@ -0,0 +1,66 @@
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ART_RUNTIME_GC_COLLECTOR_TYPE_H_
#define ART_RUNTIME_GC_COLLECTOR_TYPE_H_
#include <iosfwd>
namespace art {
namespace gc {
// Which types of collections are able to be performed.
enum CollectorType {
// No collector selected.
kCollectorTypeNone,
// Non concurrent mark-sweep.
kCollectorTypeMS,
// Concurrent mark-sweep.
kCollectorTypeCMS,
// Semi-space / mark-sweep hybrid, enables compaction.
kCollectorTypeSS,
// Heap trimming collector, doesn't do any actual collecting.
kCollectorTypeHeapTrim,
// A (mostly) concurrent copying collector.
kCollectorTypeCC,
// The background compaction of the concurrent copying collector.
kCollectorTypeCCBackground,
// Instrumentation critical section fake collector.
kCollectorTypeInstrumentation,
// Fake collector for adding or removing application image spaces.
kCollectorTypeAddRemoveAppImageSpace,
// Fake collector used to implement exclusion between GC and debugger.
kCollectorTypeDebugger,
// A homogeneous space compaction collector used in background transition
// when both foreground and background collector are CMS.
kCollectorTypeHomogeneousSpaceCompact,
// Class linker fake collector.
kCollectorTypeClassLinker,
// JIT Code cache fake collector.
kCollectorTypeJitCodeCache,
// Hprof fake collector.
kCollectorTypeHprof,
// Fake collector for installing/removing a system-weak holder.
kCollectorTypeAddRemoveSystemWeakHolder,
// Fake collector type for GetObjectsAllocated
kCollectorTypeGetObjectsAllocated,
// Fake collector type for ScopedGCCriticalSection
kCollectorTypeCriticalSection,
};
} // namespace gc
} // namespace art
#endif // ART_RUNTIME_GC_COLLECTOR_TYPE_H_

View File

@ -0,0 +1,71 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ART_RUNTIME_GC_GC_CAUSE_H_
#define ART_RUNTIME_GC_GC_CAUSE_H_
#include <iosfwd>
namespace art {
namespace gc {
// What caused the GC?
enum GcCause {
// Invalid GC cause used as a placeholder.
kGcCauseNone,
// GC triggered by a failed allocation. Thread doing allocation is blocked waiting for GC before
// retrying allocation.
kGcCauseForAlloc,
// A background GC trying to ensure there is free memory ahead of allocations.
kGcCauseBackground,
// An explicit System.gc() call.
kGcCauseExplicit,
// GC triggered for a native allocation when NativeAllocationGcWatermark is exceeded.
// (This may be a blocking GC depending on whether we run a non-concurrent collector).
kGcCauseForNativeAlloc,
// GC triggered for a collector transition.
kGcCauseCollectorTransition,
// Not a real GC cause, used when we disable moving GC (currently for GetPrimitiveArrayCritical).
kGcCauseDisableMovingGc,
// Not a real GC cause, used when we trim the heap.
kGcCauseTrim,
// Not a real GC cause, used to implement exclusion between GC and instrumentation.
kGcCauseInstrumentation,
// Not a real GC cause, used to add or remove app image spaces.
kGcCauseAddRemoveAppImageSpace,
// Not a real GC cause, used to implement exclusion between GC and debugger.
kGcCauseDebugger,
// GC triggered for background transition when both foreground and background collector are CMS.
kGcCauseHomogeneousSpaceCompact,
// Class linker cause, used to guard filling art methods with special values.
kGcCauseClassLinker,
// Not a real GC cause, used to implement exclusion between code cache metadata and GC.
kGcCauseJitCodeCache,
// Not a real GC cause, used to add or remove system-weak holders.
kGcCauseAddRemoveSystemWeakHolder,
// Not a real GC cause, used to prevent hprof running in the middle of GC.
kGcCauseHprof,
// Not a real GC cause, used to prevent GetObjectsAllocated running in the middle of GC.
kGcCauseGetObjectsAllocated,
// GC cause for the profile saver.
kGcCauseProfileSaver,
// GC cause for running an empty checkpoint.
kGcCauseRunEmptyCheckpoint,
};
} // namespace gc
} // namespace art
#endif // ART_RUNTIME_GC_GC_CAUSE_H_

View File

@ -28,8 +28,8 @@ extern "C" {
void initHideApi(JNIEnv *env);
bool compileMethod(void *artMethod, void *thread);
void suspendVM();
void resumeVM();
void suspendVM(void *);
void resumeVM(void *);
bool canGetObject();
jobject getJavaObject(JNIEnv* env, void* thread, void* address);

View File

@ -7,6 +7,8 @@
#include "../includes/log.h"
#include "../includes/utils.h"
#include "../includes/trampoline_manager.h"
#include "../includes/art_collector_type.h"
#include "../includes/art_gc_cause.h"
extern int SDK_INT;
@ -17,8 +19,10 @@ extern "C" {
bool (*jitCompileMethod)(void*, void*, void*, bool) = nullptr;
bool (*jitCompileMethodQ)(void*, void*, void*, bool, bool) = nullptr;
void (*innerSuspendVM)() = nullptr;
void (*innerResumeVM)() = nullptr;
void (*scoped_suspend_all_ctor)(void *, const char *, bool) = nullptr;
void (*scoped_suspend_all_dtor)(void *) = nullptr;
void (*scoped_gc_critical_section_ctor)(void *, void *, art::gc::GcCause, art::gc::CollectorType) = nullptr;
void (*scoped_gc_critical_section_dtor)(void *) = nullptr;
jobject (*addWeakGlobalRef)(JavaVM *, void *, void *) = nullptr;
@ -101,11 +105,14 @@ extern "C" {
//init suspend
innerSuspendVM = reinterpret_cast<void (*)()>(getSymCompat(art_lib_path,
"_ZN3art3Dbg9SuspendVMEv"));
innerResumeVM = reinterpret_cast<void (*)()>(getSymCompat(art_lib_path,
"_ZN3art3Dbg8ResumeVMEv"));
scoped_suspend_all_ctor = reinterpret_cast<decltype(scoped_suspend_all_ctor)>(getSymCompat(art_lib_path,
"_ZN3art16ScopedSuspendAllC2EPKcb"));
scoped_suspend_all_dtor = reinterpret_cast<decltype(scoped_suspend_all_dtor)>(getSymCompat(art_lib_path,
"_ZN3art16ScopedSuspendAllD2Ev"));
scoped_gc_critical_section_ctor = reinterpret_cast<decltype(scoped_gc_critical_section_ctor)>(getSymCompat(art_lib_path,
"_ZN3art2gc23ScopedGCCriticalSectionC2EPNS_6ThreadENS0_7GcCauseENS0_13CollectorTypeE"));
scoped_gc_critical_section_dtor = reinterpret_cast<decltype(scoped_gc_critical_section_dtor)>(getSymCompat(art_lib_path,
"_ZN3art2gc23ScopedGCCriticalSectionD2Ev"));
//init for getObject & JitCompiler
const char* add_weak_ref_sym;
@ -173,16 +180,18 @@ extern "C" {
return ret;
}
void suspendVM() {
if (innerSuspendVM == nullptr || innerResumeVM == nullptr)
void suspendVM(void * thiz) {
if (scoped_suspend_all_ctor == nullptr || scoped_suspend_all_dtor == nullptr || scoped_gc_critical_section_ctor == nullptr || scoped_gc_critical_section_dtor == nullptr)
return;
innerSuspendVM();
scoped_gc_critical_section_ctor(thiz, getCurrentThread(), art::gc::kGcCauseDebugger, art::gc::kCollectorTypeDebugger);
scoped_suspend_all_ctor(thiz, "Sandhook", false);
}
void resumeVM() {
if (innerSuspendVM == nullptr || innerResumeVM == nullptr)
void resumeVM(void * thiz) {
if (scoped_suspend_all_ctor == nullptr || scoped_suspend_all_dtor == nullptr || scoped_gc_critical_section_ctor == nullptr || scoped_gc_critical_section_dtor == nullptr)
return;
innerResumeVM();
scoped_gc_critical_section_dtor(thiz);
scoped_suspend_all_dtor(thiz);
}
bool canGetObject() {

View File

@ -21,8 +21,12 @@ namespace SandHook {
class StopTheWorld {
public:
inline StopTheWorld() { suspendVM(); }
inline ~StopTheWorld() { resumeVM(); }
inline StopTheWorld() { suspendVM(this); }
inline ~StopTheWorld() { resumeVM(this); }
private:
void* self_;
const char* section_name_;
const char* old_no_suspend_reason_;
};
}

View File

@ -1,48 +0,0 @@
/*
* This file is part of LSPosed.
*
* LSPosed is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LSPosed is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LSPosed. If not, see <https://www.gnu.org/licenses/>.
*
* Copyright (C) 2020 EdXposed Contributors
* Copyright (C) 2021 LSPosed Contributors
*/
#ifndef ART_RUNTIME_GC_COLLECTOR_GC_TYPE_H_
#define ART_RUNTIME_GC_COLLECTOR_GC_TYPE_H_
#include <iosfwd>
namespace art {
namespace gc {
namespace collector {
// The type of collection to be performed. The ordering of the enum matters, it is used to
// determine which GCs are run first.
enum GcType {
// Placeholder for when no GC has been performed.
kGcTypeNone,
// Sticky mark bits GC that attempts to only free objects allocated since the last GC.
kGcTypeSticky,
// Partial GC that marks the application heap but not the Zygote.
kGcTypePartial,
// Full GC that marks and frees in both the application and Zygote heap.
kGcTypeFull,
// Number of different GC types.
kGcTypeMax,
};
std::ostream &operator<<(std::ostream &os, const GcType &policy);
} // namespace collector
} // namespace gc
} // namespace art
#endif // ART_RUNTIME_GC_COLLECTOR_GC_TYPE_H_

View File

@ -0,0 +1,64 @@
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ART_RUNTIME_GC_COLLECTOR_GC_TYPE_H_
#define ART_RUNTIME_GC_COLLECTOR_GC_TYPE_H_
#include <iosfwd>
namespace art {
namespace gc {
// Which types of collections are able to be performed.
enum CollectorType {
// No collector selected.
kCollectorTypeNone,
// Non concurrent mark-sweep.
kCollectorTypeMS,
// Concurrent mark-sweep.
kCollectorTypeCMS,
// Semi-space / mark-sweep hybrid, enables compaction.
kCollectorTypeSS,
// Heap trimming collector, doesn't do any actual collecting.
kCollectorTypeHeapTrim,
// A (mostly) concurrent copying collector.
kCollectorTypeCC,
// The background compaction of the concurrent copying collector.
kCollectorTypeCCBackground,
// Instrumentation critical section fake collector.
kCollectorTypeInstrumentation,
// Fake collector for adding or removing application image spaces.
kCollectorTypeAddRemoveAppImageSpace,
// Fake collector used to implement exclusion between GC and debugger.
kCollectorTypeDebugger,
// A homogeneous space compaction collector used in background transition
// when both foreground and background collector are CMS.
kCollectorTypeHomogeneousSpaceCompact,
// Class linker fake collector.
kCollectorTypeClassLinker,
// JIT Code cache fake collector.
kCollectorTypeJitCodeCache,
// Hprof fake collector.
kCollectorTypeHprof,
// Fake collector for installing/removing a system-weak holder.
kCollectorTypeAddRemoveSystemWeakHolder,
// Fake collector type for GetObjectsAllocated
kCollectorTypeGetObjectsAllocated,
// Fake collector type for ScopedGCCriticalSection
kCollectorTypeCriticalSection,
};
} // namespace gc
} // namespace art
#endif // ART_RUNTIME_GC_COLLECTOR_GC_TYPE_H_

View File

@ -1,21 +1,17 @@
/*
* This file is part of LSPosed.
* Copyright (C) 2014 The Android Open Source Project
*
* LSPosed is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* LSPosed is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* http://www.apache.org/licenses/LICENSE-2.0
*
* You should have received a copy of the GNU General Public License
* along with LSPosed. If not, see <https://www.gnu.org/licenses/>.
*
* Copyright (C) 2020 EdXposed Contributors
* Copyright (C) 2021 LSPosed Contributors
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ART_RUNTIME_GC_GC_CAUSE_H_

View File

@ -1,118 +0,0 @@
/*
* This file is part of LSPosed.
*
* LSPosed is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LSPosed is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LSPosed. If not, see <https://www.gnu.org/licenses/>.
*
* Copyright (C) 2020 EdXposed Contributors
* Copyright (C) 2021 LSPosed Contributors
*/
#pragma once
#include <base/object.h>
#include "collector/gc_type.h"
#include "gc_cause.h"
#include "../thread.h"
#include "../runtime.h"
namespace art {
namespace gc {
class Heap : public lspd::HookedObject {
private:
inline static Heap *instance_;
CREATE_MEM_FUNC_SYMBOL_ENTRY(collector::GcType, WaitForGcToComplete,
void *thiz, GcCause cause, void *threadSelf) {
if (LIKELY(WaitForGcToCompleteSym))
return WaitForGcToCompleteSym(thiz, cause, threadSelf);
return art::gc::collector::GcType::kGcTypeNone;
}
public:
Heap(void *thiz) : HookedObject(thiz) {}
static Heap *Current() {
return instance_;
}
// @ApiSensitive(Level.MIDDLE)
static void Setup(void *handle) {
int api_level = lspd::GetAndroidApiLevel();
size_t OFFSET_heap; // Get offset from art::Runtime::RunRootClinits() call in IDA
switch (api_level) {
case __ANDROID_API_O__:
[[fallthrough]];
case __ANDROID_API_O_MR1__:
if constexpr(lspd::is64) {
OFFSET_heap = 0x180;
} else {
OFFSET_heap = 0xF4;
}
break;
case __ANDROID_API_P__:
if constexpr(lspd::is64) {
OFFSET_heap = 0x1C0;
} else {
OFFSET_heap = 0x128;
}
break;
case __ANDROID_API_Q__:
if constexpr(lspd::is64) {
OFFSET_heap = 0x190;
} else {
OFFSET_heap = 0xF0;
}
break;
default:
LOGE("No valid offset for art::Runtime::heap_ found. Using Android R.");
[[fallthrough]];
case __ANDROID_API_R__:
if constexpr(lspd::is64) {
// TODO: preload band to a boolean or enum
if (lspd::GetAndroidBrand() == "meizu") {
OFFSET_heap = 0x190;
} else {
OFFSET_heap = 392;
}
} else {
// TODO: preload band to a boolean or enum
if (lspd::GetAndroidBrand() == "meizu") {
OFFSET_heap = 0xF4;
} else {
OFFSET_heap = 236;
}
}
break;
}
void *thiz = *reinterpret_cast<void **>(
reinterpret_cast<size_t>(Runtime::Current()->Get()) + OFFSET_heap);
LOGD("art::runtime::Heap object: %p", thiz);
instance_ = new Heap(thiz);
RETRIEVE_MEM_FUNC_SYMBOL(WaitForGcToComplete,
"_ZN3art2gc4Heap19WaitForGcToCompleteENS0_7GcCauseEPNS_6ThreadE");
}
ALWAYS_INLINE collector::GcType
WaitForGcToComplete(GcCause cause, void *threadSelf) const {
if (LIKELY(thiz_))
return WaitForGcToComplete(thiz_, cause, threadSelf);
return art::gc::collector::GcType::kGcTypeNone;
}
};
} // namespace gc
} // namespace art

View File

@ -0,0 +1,65 @@
/*
* This file is part of LSPosed.
*
* LSPosed is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LSPosed is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LSPosed. If not, see <https://www.gnu.org/licenses/>.
*
* Copyright (C) 2021 LSPosed Contributors
*/
#ifndef LSPOSED_SCOPED_GC_CRITICAL_SECTION_H
#define LSPOSED_SCOPED_GC_CRITICAL_SECTION_H
#include "gc_cause.h"
#include "collector_type.h"
namespace art {
namespace gc {
class GCCriticalSection {
private:
void* self_;
const char* section_name_;
};
class ScopedGCCriticalSection {
CREATE_MEM_FUNC_SYMBOL_ENTRY(void, constructor, void *thiz, void* self, GcCause cause, CollectorType collector_type) {
if (UNLIKELY(thiz == nullptr)) return;
if (LIKELY(constructorSym))
return constructorSym(thiz, self, cause, collector_type);
}
CREATE_MEM_FUNC_SYMBOL_ENTRY(void, destructor, void *thiz) {
if (UNLIKELY(thiz == nullptr)) return;
if (LIKELY(destructorSym))
return destructorSym(thiz);
}
public:
ScopedGCCriticalSection(void *self, GcCause cause, CollectorType collector_type) {
constructor(this, self, cause, collector_type);
}
~ScopedGCCriticalSection() {
destructor(this);
}
static void Setup(void *handle) {
RETRIEVE_MEM_FUNC_SYMBOL(constructor, "_ZN3art2gc23ScopedGCCriticalSectionC2EPNS_6ThreadENS0_7GcCauseENS0_13CollectorTypeE");
RETRIEVE_MEM_FUNC_SYMBOL(destructor, "_ZN3art2gc23ScopedGCCriticalSectionD2Ev");
}
private:
GCCriticalSection critical_section_;
const char* old_no_suspend_reason_;
};
}
}
#endif //LSPOSED_SCOPED_GC_CRITICAL_SECTION_H

View File

@ -0,0 +1,53 @@
/*
* This file is part of LSPosed.
*
* LSPosed is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LSPosed is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LSPosed. If not, see <https://www.gnu.org/licenses/>.
*
* Copyright (C) 2021 LSPosed Contributors
*/
#ifndef LSPOSED_THREAD_LIST_H
#define LSPOSED_THREAD_LIST_H
namespace art {
namespace thread_list {
class ScopedSuspendAll {
CREATE_MEM_FUNC_SYMBOL_ENTRY(void, constructor, void *thiz, const char * cause, bool long_suspend) {
if (UNLIKELY(thiz == nullptr)) return;
if (LIKELY(constructorSym))
return constructorSym(thiz, cause, long_suspend);
}
CREATE_MEM_FUNC_SYMBOL_ENTRY(void, destructor, void *thiz) {
if (UNLIKELY(thiz == nullptr)) return;
if (LIKELY(destructorSym))
return destructorSym(thiz);
}
public:
ScopedSuspendAll(const char * cause, bool long_suspend) {
constructor(this, cause, long_suspend);
}
~ScopedSuspendAll() {
destructor(this);
}
static void Setup(void *handle) {
RETRIEVE_MEM_FUNC_SYMBOL(constructor, "_ZN3art16ScopedSuspendAllC2EPKcb");
RETRIEVE_MEM_FUNC_SYMBOL(destructor, "_ZN3art16ScopedSuspendAllD2Ev");
}
};
}
}
#endif //LSPOSED_THREAD_LIST_H

View File

@ -23,7 +23,6 @@
#include <JNIHelper.h>
#include "jni/config_manager.h"
#include "jni/art_class_linker.h"
#include "jni/art_heap.h"
#include "jni/yahfa.h"
#include "jni/resources_hook.h"
#include <dl_util.h>
@ -134,7 +133,6 @@ namespace lspd {
RegisterEdxpResourcesHook(env);
RegisterConfigManagerMethods(env);
RegisterArtClassLinker(env);
RegisterArtHeap(env);
RegisterEdxpYahfa(env);
RegisterPendingHooks(env);
RegisterNativeAPI(env);

View File

@ -1,45 +0,0 @@
/*
* This file is part of LSPosed.
*
* LSPosed is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LSPosed is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LSPosed. If not, see <https://www.gnu.org/licenses/>.
*
* Copyright (C) 2020 EdXposed Contributors
* Copyright (C) 2021 LSPosed Contributors
*/
#include <jni.h>
#include <native_util.h>
#include <art/runtime/gc/collector/gc_type.h>
#include <art/runtime/gc/heap.h>
#include <nativehelper/jni_macros.h>
#include "art_heap.h"
namespace lspd {
LSP_DEF_NATIVE_METHOD(jint, Heap, waitForGcToComplete) {
art::gc::collector::GcType gcType = art::gc::Heap::Current()->WaitForGcToComplete(
art::gc::GcCause::kGcCauseNone, art::Thread::Current().Get());
return gcType;
}
static JNINativeMethod gMethods[] = {
LSP_NATIVE_METHOD(Heap, waitForGcToComplete, "()I")
};
void RegisterArtHeap(JNIEnv *env) {
REGISTER_LSP_NATIVE_METHODS(Heap);
}
}

View File

@ -1,27 +0,0 @@
/*
* This file is part of LSPosed.
*
* LSPosed is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LSPosed is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LSPosed. If not, see <https://www.gnu.org/licenses/>.
*
* Copyright (C) 2020 EdXposed Contributors
* Copyright (C) 2021 LSPosed Contributors
*/
#pragma once
namespace lspd {
void RegisterArtHeap(JNIEnv *);
} // namespace lspd

View File

@ -24,6 +24,10 @@
#include "native_util.h"
#include "pending_hooks.h"
#include "art/runtime/class_linker.h"
#include "art/runtime/thread_list.h"
#include "art/runtime/thread.h"
#include "art/runtime/gc/scoped_gc_critical_section.h"
namespace lspd {
@ -39,6 +43,8 @@ namespace lspd {
LSP_DEF_NATIVE_METHOD(jboolean, Yahfa, backupAndHookNative, jobject target,
jobject hook, jobject backup) {
art::gc::ScopedGCCriticalSection section(art::Thread::Current().Get(), art::gc::kGcCauseDebugger, art::gc::kCollectorTypeDebugger);
art::thread_list::ScopedSuspendAll suspend("Yahfa Hook", false);
return Java_lab_galaxy_yahfa_HookMain_backupAndHookNative(env, clazz, target, hook, backup);
}

View File

@ -35,10 +35,12 @@
#include "art/runtime/mirror/class.h"
#include "art/runtime/art_method.h"
#include "art/runtime/class_linker.h"
#include "art/runtime/gc/heap.h"
#include "art/runtime/thread.h"
#include "art/runtime/hidden_api.h"
#include "art/runtime/instrumentation.h"
#include "art/runtime/reflection.h"
#include "art/runtime/thread_list.h"
#include "art/runtime/gc/scoped_gc_critical_section.h"
std::vector<soinfo_t> linker_get_solist(); // Dobby but not in .h
@ -96,7 +98,6 @@ namespace lspd {
}
art::hidden_api::DisableHiddenApi(art_handle);
art::Runtime::Setup(art_handle);
art::gc::Heap::Setup(art_handle);
art::art_method::Setup(art_handle);
art::Thread::Setup(art_handle);
art::ClassLinker::Setup(art_handle);
@ -104,6 +105,8 @@ namespace lspd {
art::JNIEnvExt::Setup(art_handle);
art::instrumentation::DisableUpdateHookedMethodsCode(art_handle);
art::PermissiveAccessByReflection(art_handle);
art::thread_list::ScopedSuspendAll::Setup(art_handle);
art::gc::ScopedGCCriticalSection::Setup(art_handle);
art_hooks_installed = true;
LOGI("ART hooks installed");

View File

@ -51,13 +51,6 @@ public class HookMain {
// backup is just a placeholder and the constraint could be less strict
checkCompatibleMethods(target, backup, "Backup");
}
// make sure GC completed before hook
int lastGcType = Heap.waitForGcToComplete();
if (lastGcType < 0) {
Utils.logW("waitForGcToComplete failed, using fallback");
Runtime.getRuntime().gc();
}
if(!Yahfa.backupAndHookNative(target, hook, backup)){
throw new RuntimeException("Failed to hook " + target + " with " + hook);
} else {