diff --git a/core/src/main/cpp/external/SandHook/includes/art_collector_type.h b/core/src/main/cpp/external/SandHook/includes/art_collector_type.h new file mode 100644 index 00000000..3de50771 --- /dev/null +++ b/core/src/main/cpp/external/SandHook/includes/art_collector_type.h @@ -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 + +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_ diff --git a/core/src/main/cpp/external/SandHook/includes/art_gc_cause.h b/core/src/main/cpp/external/SandHook/includes/art_gc_cause.h new file mode 100644 index 00000000..a039cc0d --- /dev/null +++ b/core/src/main/cpp/external/SandHook/includes/art_gc_cause.h @@ -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 + +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_ diff --git a/core/src/main/cpp/external/SandHook/includes/hide_api.h b/core/src/main/cpp/external/SandHook/includes/hide_api.h index 4f8fba51..e7966790 100644 --- a/core/src/main/cpp/external/SandHook/includes/hide_api.h +++ b/core/src/main/cpp/external/SandHook/includes/hide_api.h @@ -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); diff --git a/core/src/main/cpp/external/SandHook/utils/hide_api.cpp b/core/src/main/cpp/external/SandHook/utils/hide_api.cpp index bdaf2de0..66edc6ad 100644 --- a/core/src/main/cpp/external/SandHook/utils/hide_api.cpp +++ b/core/src/main/cpp/external/SandHook/utils/hide_api.cpp @@ -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(getSymCompat(art_lib_path, - "_ZN3art3Dbg9SuspendVMEv")); - innerResumeVM = reinterpret_cast(getSymCompat(art_lib_path, - "_ZN3art3Dbg8ResumeVMEv")); - + scoped_suspend_all_ctor = reinterpret_cast(getSymCompat(art_lib_path, + "_ZN3art16ScopedSuspendAllC2EPKcb")); + scoped_suspend_all_dtor = reinterpret_cast(getSymCompat(art_lib_path, + "_ZN3art16ScopedSuspendAllD2Ev")); + scoped_gc_critical_section_ctor = reinterpret_cast(getSymCompat(art_lib_path, + "_ZN3art2gc23ScopedGCCriticalSectionC2EPNS_6ThreadENS0_7GcCauseENS0_13CollectorTypeE")); + scoped_gc_critical_section_dtor = reinterpret_cast(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() { diff --git a/core/src/main/cpp/external/SandHook/utils/lock.h b/core/src/main/cpp/external/SandHook/utils/lock.h index a8485469..ba683d7b 100644 --- a/core/src/main/cpp/external/SandHook/utils/lock.h +++ b/core/src/main/cpp/external/SandHook/utils/lock.h @@ -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_; }; } diff --git a/core/src/main/cpp/main/include/art/runtime/gc/collector/gc_type.h b/core/src/main/cpp/main/include/art/runtime/gc/collector/gc_type.h deleted file mode 100644 index da0dade3..00000000 --- a/core/src/main/cpp/main/include/art/runtime/gc/collector/gc_type.h +++ /dev/null @@ -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 . - * - * 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 - -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_ \ No newline at end of file diff --git a/core/src/main/cpp/main/include/art/runtime/gc/collector_type.h b/core/src/main/cpp/main/include/art/runtime/gc/collector_type.h new file mode 100644 index 00000000..fd7cc9be --- /dev/null +++ b/core/src/main/cpp/main/include/art/runtime/gc/collector_type.h @@ -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 + +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_ \ No newline at end of file diff --git a/core/src/main/cpp/main/include/art/runtime/gc/gc_cause.h b/core/src/main/cpp/main/include/art/runtime/gc/gc_cause.h index 4017f5c2..5ba97b0e 100644 --- a/core/src/main/cpp/main/include/art/runtime/gc/gc_cause.h +++ b/core/src/main/cpp/main/include/art/runtime/gc/gc_cause.h @@ -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 . - * - * 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_ diff --git a/core/src/main/cpp/main/include/art/runtime/gc/heap.h b/core/src/main/cpp/main/include/art/runtime/gc/heap.h deleted file mode 100644 index e2962590..00000000 --- a/core/src/main/cpp/main/include/art/runtime/gc/heap.h +++ /dev/null @@ -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 . - * - * Copyright (C) 2020 EdXposed Contributors - * Copyright (C) 2021 LSPosed Contributors - */ - -#pragma once - -#include -#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( - reinterpret_cast(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 diff --git a/core/src/main/cpp/main/include/art/runtime/gc/scoped_gc_critical_section.h b/core/src/main/cpp/main/include/art/runtime/gc/scoped_gc_critical_section.h new file mode 100644 index 00000000..e060fc60 --- /dev/null +++ b/core/src/main/cpp/main/include/art/runtime/gc/scoped_gc_critical_section.h @@ -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 . + * + * 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 diff --git a/core/src/main/cpp/main/include/art/runtime/thread_list.h b/core/src/main/cpp/main/include/art/runtime/thread_list.h new file mode 100644 index 00000000..203aff66 --- /dev/null +++ b/core/src/main/cpp/main/include/art/runtime/thread_list.h @@ -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 . + * + * 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 diff --git a/core/src/main/cpp/main/src/context.cpp b/core/src/main/cpp/main/src/context.cpp index 5e07dd77..f02c7104 100644 --- a/core/src/main/cpp/main/src/context.cpp +++ b/core/src/main/cpp/main/src/context.cpp @@ -23,7 +23,6 @@ #include #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 @@ -134,7 +133,6 @@ namespace lspd { RegisterEdxpResourcesHook(env); RegisterConfigManagerMethods(env); RegisterArtClassLinker(env); - RegisterArtHeap(env); RegisterEdxpYahfa(env); RegisterPendingHooks(env); RegisterNativeAPI(env); diff --git a/core/src/main/cpp/main/src/jni/art_heap.cpp b/core/src/main/cpp/main/src/jni/art_heap.cpp deleted file mode 100644 index b834d11c..00000000 --- a/core/src/main/cpp/main/src/jni/art_heap.cpp +++ /dev/null @@ -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 . - * - * Copyright (C) 2020 EdXposed Contributors - * Copyright (C) 2021 LSPosed Contributors - */ - -#include -#include -#include -#include -#include -#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); - } - -} \ No newline at end of file diff --git a/core/src/main/cpp/main/src/jni/art_heap.h b/core/src/main/cpp/main/src/jni/art_heap.h deleted file mode 100644 index af90ce0e..00000000 --- a/core/src/main/cpp/main/src/jni/art_heap.h +++ /dev/null @@ -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 . - * - * Copyright (C) 2020 EdXposed Contributors - * Copyright (C) 2021 LSPosed Contributors - */ - -#pragma once - -namespace lspd { - - void RegisterArtHeap(JNIEnv *); - -} // namespace lspd diff --git a/core/src/main/cpp/main/src/jni/yahfa.cpp b/core/src/main/cpp/main/src/jni/yahfa.cpp index c44d3f78..504dc6ec 100644 --- a/core/src/main/cpp/main/src/jni/yahfa.cpp +++ b/core/src/main/cpp/main/src/jni/yahfa.cpp @@ -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); } diff --git a/core/src/main/cpp/main/src/native_hook.cpp b/core/src/main/cpp/main/src/native_hook.cpp index 8f98a83b..1000f942 100644 --- a/core/src/main/cpp/main/src/native_hook.cpp +++ b/core/src/main/cpp/main/src/native_hook.cpp @@ -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 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"); diff --git a/core/src/main/java/io/github/lsposed/lspd/core/yahfa/HookMain.java b/core/src/main/java/io/github/lsposed/lspd/core/yahfa/HookMain.java index 63115101..524e36a1 100644 --- a/core/src/main/java/io/github/lsposed/lspd/core/yahfa/HookMain.java +++ b/core/src/main/java/io/github/lsposed/lspd/core/yahfa/HookMain.java @@ -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 {