[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:
parent
8abf2bd86b
commit
7db7b62ab6
|
|
@ -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_
|
||||
|
|
@ -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_
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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_
|
||||
|
|
@ -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_
|
||||
|
|
@ -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_
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
Loading…
Reference in New Issue